1. 什么是Redis?
Redis是完全開源的免費(fèi)的。遵守BSD協(xié)議。一個(gè)高性能的key-value數(shù)據(jù)庫(kù)。
Redis與其他kv緩存產(chǎn)品有以下三個(gè)特點(diǎn):
- Redis支持?jǐn)?shù)據(jù)的持久化,可以將內(nèi)存中的數(shù)據(jù)保存在磁盤中,重啟的時(shí)候可以再次加載進(jìn)行使用(兩種持久化手段:aof和rdb。一個(gè)file追加,一個(gè)快照)
- Redis不僅僅支持簡(jiǎn)單的 key-value類型的數(shù)據(jù),同時(shí)還提供list,set,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)。
- Redis支持?jǐn)?shù)據(jù)的備份。即master-slave模式的數(shù)據(jù)備份。
Redis的優(yōu)勢(shì):
- 性能極高。Redis的讀是11w/s。寫是8.1w/s
- 豐富的數(shù)據(jù)類型。 Redis支持二進(jìn)制案例的Strings,Lists,Hashes,Sets以及ordered Sets數(shù)據(jù)類型操作
- 原子。Redis的所有操作都是原子性的。意思是要么成功要么失敗。當(dāng)然了這里說的是單個(gè)操作是原子性的。而多個(gè)操作的話要用multi和exec指令包起來,手動(dòng)去維護(hù)原子性。(單個(gè)操作的原子性和memcached類似。多個(gè)操作的手動(dòng)維護(hù)原子性是memcached沒有的功能)
- 豐富的特性。 Redis還支持訂閱和發(fā)布(subscribe/publish)。通知。key過期等特性。
Redis與其他key-value存儲(chǔ)有什么不同?
- Redis有著更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)并且提供對(duì)他們的原子性操作、這是一個(gè)不同于其他數(shù)據(jù)庫(kù)的進(jìn)化路徑。Redis的數(shù)據(jù)類型都是基于基本數(shù)據(jù)結(jié)構(gòu)的同事對(duì)程序員透明,無需進(jìn)行額外的抽象。
- Redis雖然是運(yùn)行在內(nèi)存中但是可以持久化到磁盤。所以在對(duì)不同數(shù)據(jù)集進(jìn)行高速讀寫的時(shí)候需要權(quán)衡內(nèi)存。因?yàn)閿?shù)據(jù)量不能大于硬件內(nèi)存。在內(nèi)存數(shù)據(jù)庫(kù)方面的另一個(gè)優(yōu)點(diǎn)是:相比在磁盤上相同的復(fù)雜的數(shù)據(jù)結(jié)構(gòu),在內(nèi)存中操作起來非常簡(jiǎn)單。這樣redis可以做很多內(nèi)部復(fù)雜性很強(qiáng)的事情。同時(shí),在磁盤格式方面他們是緊湊的以追加的形式產(chǎn)生的(aof的全程 append only file)。因?yàn)樗麄儾⒉恍枰M(jìn)行隨機(jī)訪問。
2. Redis的數(shù)據(jù)類型?
Redis支持五種數(shù)據(jù)類型: String 字符串。 Hash 哈希。 List 列表。Set 集合。 zsetsorted set 有序集合。
我們實(shí)際項(xiàng)目中比較常用的是String。而且在Spring boot整合Redis的時(shí)候也提供兩種bean:一種是RedisTemplate。還有一種就是專門字符串的StringRedisTemplate。
另外如果你對(duì)Redis用的比較熟練,應(yīng)該還知道一些數(shù)據(jù)結(jié)構(gòu): HyperLogLog。Geo,pub/sub.bitmap等
- HyperLogLog:這個(gè)其實(shí)是也是用來去重和統(tǒng)計(jì)的?;贖LL算法實(shí)現(xiàn)的。好像是分桶思想。這個(gè)數(shù)據(jù)結(jié)構(gòu)只有三個(gè)api:
增加集合(自動(dòng)去重)。合并集合(自動(dòng)去重)。查看當(dāng)前集合中元素?cái)?shù)(去重后結(jié)果)
和set相比優(yōu)點(diǎn)是當(dāng)數(shù)據(jù)量很大,set的判斷不方便,而HLL占用的內(nèi)存是一定的。但是其有一些誤差。 - GEO:地理信息定位,存儲(chǔ)經(jīng)緯度,計(jì)算兩地距離,范圍計(jì)算等
- bitmap:用于統(tǒng)計(jì)的,底層好像是二進(jìn)制。用位操作來統(tǒng)計(jì)。比如簽到。
關(guān)于redis的數(shù)據(jù)結(jié)構(gòu)我之前整理過并且還有一些api的調(diào)用方法和簡(jiǎn)單的理解。感興趣的可以去看下我另一篇文章:http://www.lxweimin.com/p/58a77ee1a77f - pub/sub:這個(gè)是不是數(shù)據(jù)結(jié)構(gòu),而是一個(gè)功能,發(fā)布訂閱。
3. 使用Redis有哪些好處?
- 速度快,因?yàn)閿?shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1).
- 支持豐富的數(shù)據(jù)類型:String,List,Set,Zset,Hash.
- 支持事務(wù)。操作都是原子性的,所謂的原子性就是對(duì)數(shù)據(jù)的更改要么全部執(zhí)行,要么全部不執(zhí)行。
- 豐富的特性:可用于緩存,消息,按key設(shè)置過期時(shí)間,過期自動(dòng)刪除。
4. Redis相比于Memcached有哪些優(yōu)勢(shì)?
- Memcached所有的值都是簡(jiǎn)單的字符串、Redis支持更為豐富 數(shù)據(jù)類型。
- Redis的速度比Memcached快(這個(gè)快慢其實(shí)要看數(shù)據(jù)結(jié)構(gòu),但是因?yàn)镽edis是單核的。Memcached是多核的。所以數(shù)據(jù)量小的情況下redis優(yōu)于Memcached)。
- Redis支持持久化數(shù)據(jù)。
4. Memcacahed與Redis的去被都有哪些?
(可能是因?yàn)槲疫@兩個(gè)東西是接連整理的,只能說兩者的區(qū)別被翻來覆去的說。。)
- 存儲(chǔ)方式。 Memcached是完全數(shù)據(jù)存在內(nèi)存的,斷電即失。而且數(shù)據(jù)不能超過內(nèi)存大小。Redis有持久化功能。
- 數(shù)據(jù)類型中Redis支持多種數(shù)據(jù)類型。而Memcached只支持字符串。
- 使用的底層模型不同。他們之間的底層實(shí)現(xiàn)方式以及客戶端之間的通訊的應(yīng)用協(xié)議都不一樣。
Redis直接自己構(gòu)建了vm機(jī)制。因?yàn)橐话愕南到y(tǒng)。調(diào)用系統(tǒng)函數(shù)的話會(huì)浪費(fèi)一定的時(shí)間去請(qǐng)求。
6. Redis是單進(jìn)程單線程的?
對(duì)的。Redis是單進(jìn)程單線程的。Redis利用隊(duì)列技術(shù)將并發(fā)訪問變?yōu)榇性L問。消除了傳統(tǒng)數(shù)據(jù)庫(kù)串行控制的開銷。
7. 一個(gè)字符串類型的值能存儲(chǔ)最大容量是多少?
512M(這里可以回憶一下Memcached,單節(jié)點(diǎn)最大1MB,單個(gè)key最長(zhǎng)250字節(jié))
8. Redis的持久化機(jī)制是什么?各自的優(yōu)缺點(diǎn)是什么?
Redis提供兩種持久化機(jī)制。分別是RDB和AOF、
RDB持久化:這個(gè)是指數(shù)據(jù)集快照的方式半持久化模式。記錄Redis數(shù)據(jù)庫(kù)的所有當(dāng)前鍵值對(duì)。在某個(gè)時(shí)間點(diǎn)將數(shù)據(jù)寫入一個(gè)臨時(shí)文件。持久化結(jié)束后,用這個(gè)臨時(shí)文件替換上次持久化的文件。達(dá)到數(shù)據(jù)恢復(fù)。
RDB的優(yōu)點(diǎn):
- 只有一個(gè)dump.rdb,方便持久化
- 容災(zāi)性好,一個(gè)文件可以保存到安全的磁盤
- 性能最大化。fork子進(jìn)程來完成寫操作。主進(jìn)程可以繼續(xù)處理命令。所以是IO最大化。使用單獨(dú)的子進(jìn)程進(jìn)行持久化,主進(jìn)程不會(huì)有任何IO操作,保證了Redis的高性能
- 相對(duì)于數(shù)據(jù)集比較大的時(shí)候,比AOF的啟動(dòng)效率更高
RDB的缺點(diǎn):
數(shù)據(jù)安全性低。RDB是隔一段時(shí)間持久化一次。比如五分鐘持久化一次。但是如果在4分50秒的時(shí)候redis宕機(jī)了,那么這4分50秒的數(shù)據(jù)沒有持久化,也就是會(huì)丟失。
AOF持久化:全稱是append - only - file。也就是所有的命令行記錄以redis命令請(qǐng)求協(xié)議的格式完全持久化存儲(chǔ)。保存為aof文件。
AOF的優(yōu)點(diǎn):
- 數(shù)據(jù)安全。aof持久化可以配置appendfsync屬性。如果設(shè)置為always。則每一次命令操作都記錄到aof文件中。
- 通過append模式寫文件。及時(shí)中途服務(wù)器宕機(jī)。也可以通過redis-check-aof工具解決數(shù)據(jù)一致性問題。
- AOF機(jī)制的rewrite模式。文件過大時(shí)會(huì)對(duì)命令進(jìn)行合并重寫,可以刪除其中的某些指令(比如誤操作的flushall)
AOF的缺點(diǎn):
- AOF文件比RDB文件大,而且恢復(fù)速度慢
- 數(shù)據(jù)集大的時(shí)候,AOF是不斷追加,會(huì)越來越大、比RDB啟動(dòng)效率低。
當(dāng)然了,在實(shí)際工作中,我們一般都是AOF和RDB配合使用的。
9. Redis常用性能問題和解決方案
- Master最好不要寫內(nèi)存快照。因?yàn)槿绻鸐aster寫內(nèi)存快照,save命令調(diào)用rdbSave函數(shù)會(huì)阻塞主線程的工作。當(dāng)快照比較大時(shí)對(duì)性能影響是非常大的。會(huì)間斷性暫停服務(wù)。
- 如果數(shù)據(jù)比較重要。某個(gè)Slave開啟AOF備份數(shù)據(jù)。策略可以設(shè)置為每秒同步一次。
- 為了主從復(fù)制的速度和連接的穩(wěn)定性。Master和Slave最好在同一個(gè)局域網(wǎng)內(nèi)。
- 盡量避免在壓力很大的主庫(kù)上增加從。
- 主從復(fù)制不要用圖狀結(jié)構(gòu)而用單向鏈表結(jié)構(gòu)更為穩(wěn)定。即
Master<-Slave1<-Slave2<-Slave3這種。這樣的結(jié)構(gòu)方便解決單點(diǎn)故障問題,實(shí)現(xiàn)Slave對(duì)Master的替換。如果Master掛了,可以立刻啟用Slave1做Master,其他的保持不變。
10. Redis過期鍵的刪除策略?
- 定時(shí)刪除。在設(shè)置鍵的過期時(shí)間的同時(shí),創(chuàng)建一個(gè)定時(shí)器timer。讓定時(shí)器在鍵的過期時(shí)間來臨時(shí),立即執(zhí)行對(duì)鍵的刪除操作。
- 惰性刪除。放任鍵過期不管,但是每次從鍵空間中獲取鍵的時(shí)候都檢查取得的鍵是否過期,如果過期的話,就刪除該鍵。如果沒過期則返回該鍵。
- 定期刪除。每隔一段時(shí)間程序就對(duì)數(shù)據(jù)庫(kù)進(jìn)行一次檢查,刪除里面過期的鍵。至于刪除多少過期鍵或者檢查多少個(gè)數(shù)據(jù)庫(kù)都由算法決定。
11. Redis的回收策略(淘汰策略)?
- volatile-LRU:從已經(jīng)設(shè)置過期時(shí)間的數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰。
- volatile-TTL:從已經(jīng)設(shè)置過期時(shí)間的數(shù)據(jù)集中挑選將要過期的數(shù)據(jù)淘汰。
- volatile-random:從已經(jīng)設(shè)置過期時(shí)間的數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰。
- allkeys-LRU: 從所有數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰
- allkeys-random: 從所有數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰
- no-enviction:禁止刪除數(shù)據(jù)
注意上面六種機(jī)制:volatile和allkeys是規(guī)定選擇的key的范圍。而TTL,LRU,RANDOM是三種不同的淘汰策略。最后一種是永不回收策略。
而使用策略的規(guī)則或者說應(yīng)該怎么選?
- 如果數(shù)據(jù)呈現(xiàn)冪律分布,也就是一部分?jǐn)?shù)據(jù)訪問頻率高,一部分?jǐn)?shù)據(jù)訪問頻率低,則建議使用allkeys-lru
- 如果數(shù)據(jù)呈現(xiàn)平等分布,也就是所有數(shù)據(jù)訪問頻率差不多相同,則建議使用allkeys-random。
12. 為什么Redis需要把所有數(shù)據(jù)放到內(nèi)存中?
RedisEileen達(dá)到最快的讀寫速度所以將數(shù)據(jù)都讀到內(nèi)存中。并通過異步的方式將數(shù)據(jù)寫入磁盤。
所以redis同時(shí)具有快速和數(shù)據(jù)持久化的特征。如果不講數(shù)據(jù)放在內(nèi)存中,磁盤I/O速度會(huì)嚴(yán)重影響Redis性能。在內(nèi)存越來越便宜的今天,redis將會(huì)越來越受歡迎。
如果設(shè)置了最大使用的內(nèi)存,則數(shù)據(jù)已有記錄數(shù)達(dá)到內(nèi)存限制值后將不能繼續(xù)插入新值了。
13. Redis的同步機(jī)制?
其實(shí)Redis可以使用主從同步,叢叢同步。
第一次同步時(shí),主節(jié)點(diǎn)做一次bgsave,并且同時(shí)將后續(xù)修改操作記錄到內(nèi)存buffer。待完成后將rdb文件全量同步到復(fù)制節(jié)點(diǎn),復(fù)制節(jié)點(diǎn)接收完成后將rdb鏡像加載到內(nèi)存。加載完成后,再通知主節(jié)點(diǎn)將期間修改的操作記錄同步到復(fù)制節(jié)點(diǎn)進(jìn)行重放就完成了同步過程(其實(shí)這里可以說一些別的:比如mysql的遷庫(kù):我們也可以采用類似的思路:首先當(dāng)前數(shù)據(jù)庫(kù)備份。然后拿著這個(gè)備份去新的數(shù)據(jù)庫(kù)運(yùn)行。如果數(shù)據(jù)量很大這個(gè)會(huì)時(shí)間比較長(zhǎng)。但是等備份數(shù)據(jù)庫(kù)結(jié)束以后可以暫停當(dāng)前項(xiàng)目。然后再次備份原庫(kù)。因?yàn)橹坝袀浞荩栽俅蝹浞輹?huì)在上一個(gè)的基礎(chǔ)上操作,也就是這期間新插入的數(shù)據(jù)會(huì)同步,但是時(shí)間會(huì)短很多。然后同理把這個(gè)備份在新庫(kù)中運(yùn)行。然后項(xiàng)目指向新數(shù)據(jù)庫(kù)。完成遷移)。
14. Pipeline有什么好處?為什么要用pipeline?
其可以將多次IO往返的時(shí)間縮減為一次。前提是pipeline執(zhí)行的指令之間沒有因果關(guān)系。
15. Redis集群的原理是什么?
這個(gè)答案說的問題有點(diǎn)大。我們知道Redis本身可以實(shí)現(xiàn)主從。但是單純的主從其實(shí)是有問題的。主機(jī)可以寫,從機(jī)不可以寫只能讀(默認(rèn)的)。主機(jī)中的所有內(nèi)容都會(huì)被同步到從機(jī)中。默認(rèn)情況下,主機(jī)宕機(jī)了,從機(jī)也只能是從機(jī)。
這樣其實(shí)整個(gè)redis都崩了。所以這樣肯定是不對(duì)的。然后進(jìn)化版就是哨兵模式。這也是很出名的所謂的redis的一主二從三哨兵的順口溜。繼續(xù)說這個(gè)題:
Redis Sentinal(哨兵)著眼于高可用。在master宕機(jī)時(shí)會(huì)自動(dòng)將slave提升為master,繼續(xù)提供服務(wù)。
Redis Cluster(集群)著眼于擴(kuò)展性,在單個(gè)redis內(nèi)存不足時(shí),使用Cluster進(jìn)行分片存儲(chǔ)。
16. Redis集群方案什么情況下會(huì)導(dǎo)致整個(gè)集群不可用?
如果有A,B,C三個(gè)節(jié)點(diǎn)的集群。如果都沒有從機(jī),那么節(jié)點(diǎn)B宕機(jī)(redis集群的key的分配不是一致性hash算法,而是xxxx..反正是哈希槽的概念。Redis中有16384個(gè)哈希槽。計(jì)算方法大概是key通過CRC16校驗(yàn)后對(duì)16384取模判斷是哪個(gè)槽)總而言之就是根據(jù)key算出落在哪個(gè)節(jié)點(diǎn)上,那么B宕機(jī)則落在B節(jié)點(diǎn)上的都不可用。
當(dāng)然如果A,B,C有從節(jié)點(diǎn),主宕機(jī)后從節(jié)點(diǎn)會(huì)上位。如果從節(jié)點(diǎn)也宕機(jī)則還是不可用。
17. Redis支持的java客戶端都有什么?
Redisson,Jedis,Lettuce。
好像之前Jedis用的比較多。但是現(xiàn)在spring boot 默認(rèn)使用的是Lettuce(spring boot 2版本。目前是2021/3.不知道以后會(huì)不會(huì)變)
18. Jedis與Redisson對(duì)比有什么優(yōu)缺點(diǎn)?
Jedis其實(shí)就好像這個(gè)名字一樣。java redis。是Redis的Java實(shí)現(xiàn)的客戶端。其API提供了比較全面的Redis命令的支持。
Redisson實(shí)現(xiàn)了分布式和可擴(kuò)展的Java數(shù)據(jù)結(jié)構(gòu)。和Jedis相比功能比較簡(jiǎn)單。不支持字符串操作,不支持排序,事務(wù),管道,分區(qū)等Redis特性。
Redisson的宗旨是促進(jìn)使用者對(duì)Redis的關(guān)注分離。從而讓使用者能夠?qū)⒕械姆旁谔幚順I(yè)務(wù)邏輯上。
19. Redis如何設(shè)置密碼以及驗(yàn)證密碼的?
設(shè)置密碼有兩種方式:
- 控制臺(tái)config set requirepass 123456
-
配置文件中配置后啟動(dòng)
配置文件配置密碼
驗(yàn)證密碼:auto 123456
20. 說說Redis哈希槽的概念?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念。Redis集群有16384個(gè)哈希槽。每個(gè)key通過CRC16校驗(yàn)后對(duì)16384取模來決定放在哪個(gè)槽。集群的每個(gè)節(jié)點(diǎn)復(fù)雜一部分hash槽。
21. Redis集群的主從復(fù)制模型是怎樣的?
為了使在部分節(jié)點(diǎn)失敗或者大部分節(jié)點(diǎn)無法通訊的情況下集群仍然可以使用,所以集群使用了主從復(fù)制模型。每個(gè)節(jié)點(diǎn)會(huì)有N-1個(gè)復(fù)制品。(這個(gè)因?yàn)閞edis集群的特性是每個(gè)節(jié)點(diǎn)負(fù)責(zé)一部分哈希槽,所以集群中一個(gè)節(jié)點(diǎn)宕機(jī)就會(huì)出問題。所以一定要有備用的,也就是主從復(fù)制。主宕機(jī)從可以上位)
22. Redis集群會(huì)有寫操作丟失么?為什么?
因?yàn)镽edis并不能保證數(shù)據(jù)的強(qiáng)一致性。這意味著在實(shí)際工作中集群在特定的條件下可能會(huì)丟失寫操作。
23. Redis集群之間是如何復(fù)制的?
異步復(fù)制
24. Redis集群的最大節(jié)點(diǎn)個(gè)數(shù)的多少?
16384個(gè)(這個(gè)是因?yàn)楣2壑挥?6384個(gè)。所以最大只能一個(gè)槽分給一個(gè)節(jié)點(diǎn)。不可能出現(xiàn)兩個(gè)槽共用一個(gè)節(jié)點(diǎn)。所以最大節(jié)點(diǎn)數(shù)也是16384)
25. Redis集群如何選擇數(shù)據(jù)庫(kù)?
Redis集群目前無法做數(shù)據(jù)庫(kù)選擇,默認(rèn)在0數(shù)據(jù)庫(kù)。
26. 如何測(cè)試Redis的連通性?
使用ping命令
27. 怎么理解Redis事務(wù)?
事務(wù)是一個(gè)單獨(dú)的隔離操作。事務(wù)中所有的命令都會(huì)被序列化。按順序的執(zhí)行。
事務(wù)在執(zhí)行的過程中,不會(huì)被其它客戶端發(fā)送過來的命令請(qǐng)求打斷。
而且事務(wù)是一個(gè)原子操作,食物中的命令要么全部被執(zhí)行,要么全部都不執(zhí)行。
28. Redis事務(wù)相關(guān)的命令有哪些?
MULTI/EXEC 這兩個(gè)其實(shí)是一對(duì)。
DISCARD 取消事務(wù)
WATCH 監(jiān)視
整體而言我們可以理解為如果想要開始事務(wù):MULTI
然后后面輸入的命令都會(huì)被寫入隊(duì)列而不是一個(gè)命令一個(gè)命令的執(zhí)行。
EXEC 命令 是可以開始執(zhí)行隊(duì)列中的命令了(這里要注意不執(zhí)行和執(zhí)行報(bào)錯(cuò)是兩個(gè)概念)
DISCARD 是說不執(zhí)行隊(duì)列中的命令了。
WATCH 就比較簡(jiǎn)單了,用來監(jiān)視一些key。在命令執(zhí)行前如果這些key被別的線程改動(dòng)過,則這整個(gè)事務(wù)就不生效了。
29. Redis key的過期時(shí)間和永久有效分別怎么設(shè)置?
EXPIRE是設(shè)置過期時(shí)間,不設(shè)置的話默認(rèn)是永久有效的
30. Redis如何做內(nèi)存優(yōu)化?
盡可能的使用散列表。散列表使用的內(nèi)存非常小,所以應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表里面。
比如有一個(gè)用戶對(duì)象,不要每一個(gè)屬性豆豆設(shè)置單獨(dú)的key,而應(yīng)該把這個(gè)用戶的所有信息存儲(chǔ)到一張散列表里。
31. Redis回收進(jìn)程如何工作的?
一個(gè)客戶端運(yùn)行了新的命令,添加了新的數(shù)據(jù)。Redis檢查內(nèi)存使用情況,如果大于maxmemory的限制,則根據(jù)設(shè)定好的策略進(jìn)行回收。一個(gè)新的命令被執(zhí)行等。
大概意思就類似倒脾酒:發(fā)現(xiàn)要倒?jié)M了就喝一口,空出地方繼續(xù)到。再發(fā)現(xiàn)要滿了溢出了再喝一口。。。
總而言之不斷的穿越內(nèi)存限制的邊界。然后到了邊界不斷的回收到邊界以下。差不多就是這么個(gè)回收過程。
32. 都有哪些辦法可以降低Redis的內(nèi)存使用情況?
可以好好利用hash,list,sorted set,set等集合類型數(shù)據(jù)結(jié)構(gòu)。因?yàn)橥ǔ:芏嘈〉膋ey-value可以用更緊湊的方式存放到一起。
比如一個(gè)用戶:有id,userName,age,三個(gè)字段。如果存儲(chǔ)成三個(gè)key。并對(duì)應(yīng)三個(gè)value。和存儲(chǔ)成一個(gè)hash類型的key,zhegekey中有三個(gè)kv。那么是hash類型的更加節(jié)省內(nèi)存。
33. Redis的內(nèi)存用完了會(huì)發(fā)生什么?
如果達(dá)到設(shè)置的上限,Redis的寫命令會(huì)返回錯(cuò)誤信息。但是讀命令還是可以正常返回的。
或者可以將Redis當(dāng)緩存來使用配置淘汰機(jī)制。就是當(dāng)Redis達(dá)到內(nèi)存上限時(shí)會(huì)刪除掉一些舊的內(nèi)容。
34. 一個(gè)Redis實(shí)例最多能存放多少的keys?List,Set,Sorted Set他們最多能存放多少個(gè)元素?
據(jù)說理論上Redis可以處理2的32次方的keys。在實(shí)際中測(cè)試,每個(gè)實(shí)例至少可以存放2.5億的keys。任何的list,set,zset也都是2的32次方。換句話說:Redis的存儲(chǔ)極限是系統(tǒng)中的可用內(nèi)存值。
35. MySQL中有2000w數(shù)據(jù),redis中只有20w數(shù)據(jù),如何保證redis中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)?
其實(shí)這個(gè)完全可以用redis的淘汰策略保證。上面就提到過redis內(nèi)存達(dá)到上限會(huì)刪除舊數(shù)據(jù)。我們可以設(shè)置一些淘汰策略。這個(gè)和Memcached類似,而且上文提到過redis的淘汰策略。可以酌情選擇。Redis提供的六種數(shù)據(jù)淘汰策略:
- volatile-lru:從設(shè)置過期時(shí)間的數(shù)據(jù)集中挑選最近最少使用的淘汰。
- volatile-ttl:從設(shè)置過期時(shí)間的數(shù)據(jù)集中挑選過期時(shí)間最近的淘汰。
- volatile-random:從設(shè)置過期時(shí)間的數(shù)據(jù)集中隨機(jī)挑選淘汰。
- allkeys-lru:所有key中挑選最近最少使用的淘汰
- allkeys-random:所有key中隨機(jī)挑選淘汰
- no-enviction:從不淘汰
36. Redis最適合的場(chǎng)景?
會(huì)話緩存(Session Cache)
最常用的一種使用Redis的情景是會(huì)話緩存。用Redis緩存會(huì)話比其他存儲(chǔ)的優(yōu)勢(shì)在于:Redis提供持久化。當(dāng)維護(hù)一個(gè)不是嚴(yán)格要求一致性的緩存時(shí),如果用戶的購(gòu)物車信息全部丟失,大部分人會(huì)不高興的。但是如果只剛剛加購(gòu)的商品丟失,很多人都不會(huì)很在意。全頁(yè)緩存(FPC)
除了基本的會(huì)話token之外,Redis還提供很簡(jiǎn)單的FPC平臺(tái)?;氐揭恢滦詥栴},即使重啟了Redis實(shí)例,因?yàn)橛写疟P的持久化,用戶也不會(huì)看到頁(yè)面加載速度的下降。這是一個(gè)極大的改進(jìn)。類似PHP的本地FPC。再次以Magento為例,Magento提供一個(gè)插件來使用Redis作為全頁(yè)緩存后端。隊(duì)列
Redis在內(nèi)存存儲(chǔ)引擎領(lǐng)域的一大優(yōu)點(diǎn)是提供list和set操作。這使得Redis可以作為一個(gè)很好的消息隊(duì)列平臺(tái)來使用。Redis作為隊(duì)列使用的操作,就類似于本地程序語(yǔ)言對(duì)list的push/pop操作。排行榜/計(jì)數(shù)器
Redis在內(nèi)存中對(duì)數(shù)字進(jìn)行遞增/遞減的操作實(shí)現(xiàn)非常好。集合和有序集合也使得我們?cè)趫?zhí)行這些操作的時(shí)候變得非常簡(jiǎn)單。Redis只是正好提供了這兩種數(shù)據(jù)結(jié)構(gòu),所以我們要從排序集合中獲取到排名最靠前的10個(gè)用戶。我們其實(shí)就已經(jīng)實(shí)現(xiàn)了排行榜。發(fā)布/訂閱
Redis的發(fā)布/訂閱功能的使用場(chǎng)景也非常多。其可以在人們社交網(wǎng)絡(luò)連接中使用??梢宰鳛槟_本觸發(fā)器,還可以建立聊天系統(tǒng)。
37. 假如Redis中有一億個(gè)key,其中有10w個(gè)key是某個(gè)固定的一直的前綴開頭的,如何將他們?nèi)空页鰜恚?/h4>
使用keys指令可以模糊搜索、當(dāng)然了keys * 是查詢?nèi)康膋ey。
追問:如果這個(gè)Redis正在給線上的業(yè)務(wù)提供服務(wù),使用keys指令會(huì)有什么問題?
這個(gè)時(shí)候有一個(gè)很重要的問題:Redis是單線程的。keys指令會(huì)導(dǎo)致線程阻塞一段時(shí)間。尤其是上面說到數(shù)據(jù)量很大的時(shí)候,所以線上服務(wù)會(huì)停頓,直到指令執(zhí)行完畢服務(wù)才能恢復(fù)。
這個(gè)時(shí)候可以使用scan指令。scan指令可以無阻塞的提取出指定模式的key列表。但是有一定的重復(fù)概率(可以客戶端去重)。而且整體的花費(fèi)時(shí)間會(huì)比keys指令長(zhǎng)。
38. 如果有大量的key需要設(shè)置同一時(shí)間過期,一般需要注意什么?
如果大量的key過期時(shí)間設(shè)置的過于集中,到了那個(gè)過期的時(shí)間點(diǎn)redis可能會(huì)出現(xiàn)短暫的卡頓現(xiàn)象。(而且從使用的角度也容易造成緩存雪崩)。這里建議在過期時(shí)間上加一個(gè)隨機(jī)值,使得過期時(shí)間分散一些。
39. 使用過Redis做異步隊(duì)列么?怎么用的?
這里先簡(jiǎn)單復(fù)習(xí)一下redis中關(guān)于list 的操作:
一般使用list結(jié)構(gòu)作為隊(duì)列,rpush生產(chǎn)消息(從右插入),lpop消費(fèi)消息(從左消費(fèi))。當(dāng)lpop沒有消息的時(shí)候,適當(dāng)?shù)膕leep一會(huì)再重試?。ㄆ鋵?shí)我覺得這里只要保證先插先走就行了,所以從左插入從右消費(fèi)也是ok 的)
追問:如果不使用sleep要怎么實(shí)現(xiàn)?
list還有個(gè)指令叫blpop/brpop。在沒有消息的時(shí)候,會(huì)阻塞住直到消息到來。(b可以理解為blocking)
追問:能不能生產(chǎn)一次消費(fèi)多次呢?
這個(gè)可以使用pub/sub訂閱者模式,可以實(shí)現(xiàn)1:N的消息隊(duì)列
追問:pub/sub有什么缺點(diǎn)?
在消費(fèi)者下線的情況下,生產(chǎn)的消息會(huì)丟失。專業(yè)的消息隊(duì)列RabbitMQ就不會(huì)。
追問:Redis如何實(shí)現(xiàn)延時(shí)隊(duì)列?
這個(gè)可以使用sorted set來實(shí)現(xiàn)。因?yàn)閟orted set插入的時(shí)候可以拿時(shí)間戳作為score。消息內(nèi)容作為key。而消費(fèi)者想要獲取N秒前的消息時(shí),用zrangebyscore命令獲取N秒錢的數(shù)據(jù)。
40. Redis分布式鎖是怎么回事?
先拿setnx來爭(zhēng)搶suo.搶到之后用expire給鎖加個(gè)過期時(shí)間防止忘了釋放鎖。
當(dāng)然為了防止在setnx之后expire之前進(jìn)程carch或者重啟(這種情況鎖會(huì)一直得不到釋放),我們可以把setnx和expire合成一條指令來用。
至此,1000道互聯(lián)網(wǎng)java面試題中Redis部分就結(jié)束了,其實(shí)我真正記錄一遍后會(huì)發(fā)現(xiàn)這些問題很雜,而且回答幾乎都很淺顯。雖然之前我自認(rèn)對(duì)redis有一定的了解,并且前不久才系統(tǒng)的整理過redis知識(shí)點(diǎn)。但是看這些題目有的還需要額外去百度一些附加知識(shí)。我只能說這些面試題適合作為一個(gè)大綱來記錄。單絕對(duì)不止是背下來上面這些文字就萬(wàn)事大吉了!因?yàn)槿绻撬烙浻脖成厦娴奈淖值脑挄?huì)非常經(jīng)不起考驗(yàn)!稍微細(xì)問就容易卡住。這里還是建議每一道題往深了看,或者多看看基礎(chǔ)的東西之類的。
如果本篇筆記稍微幫到了你請(qǐng)記得點(diǎn)個(gè)喜歡點(diǎn)個(gè)關(guān)注。也祝大家工作順順利利!最近看群里聊天,一個(gè)人說學(xué)的越多越發(fā)現(xiàn)自己淺薄,其實(shí)是很有道理的話。但是哪怕如此多學(xué),多看,我也相信依舊是有用的。無論是不是在面試的朋友們,要相信努力不會(huì)騙人!