大剑无锋之Redis面试题【推荐】
1.Redis 是一個(gè)基于內(nèi)存的高性能key-value數(shù)據(jù)庫(kù)。
2.Redis相比memcached有哪些優(yōu)勢(shì):
-
memcached所有的值均是簡(jiǎn)單的字符串,redis作為其替代者,支持更為豐富的數(shù)據(jù)類型
-
redis的速度比memcached快很多
-
redis可以持久化其數(shù)據(jù)
3.Redis是單線程
redis利用隊(duì)列技術(shù)將并發(fā)訪問(wèn)變?yōu)榇性L問(wèn),消除了傳統(tǒng)數(shù)據(jù)庫(kù)串行控制的開(kāi)銷
4.Reids常用5種數(shù)據(jù)類型
-
string,list,set,sorted set,hash
6.Reids6種淘汰策略:
-
noeviction: 不刪除策略, 達(dá)到最大內(nèi)存限制時(shí), 如果需要更多內(nèi)存, 直接返回錯(cuò)誤信息。大多數(shù)寫(xiě)命令都會(huì)導(dǎo)致占用更多的內(nèi)存(有極少數(shù)會(huì)例外。
-
**allkeys-lru:**所有key通用; 優(yōu)先刪除最近最少使用(less recently used ,LRU) 的 key。
-
**volatile-lru:**只限于設(shè)置了 expire 的部分; 優(yōu)先刪除最近最少使用(less recently used ,LRU) 的 key。
-
**allkeys-random:**所有key通用; 隨機(jī)刪除一部分 key。
-
volatile-random: 只限于設(shè)置了?expire?的部分; 隨機(jī)刪除一部分 key。
-
volatile-ttl: 只限于設(shè)置了?expire?的部分; 優(yōu)先刪除剩余時(shí)間(time to live,TTL) 短的key。
7.Redis的并發(fā)競(jìng)爭(zhēng)問(wèn)題如何解決?
單進(jìn)程單線程模式,采用隊(duì)列模式將并發(fā)訪問(wèn)變?yōu)榇性L問(wèn)。Redis本身沒(méi)有鎖的概念,Redis對(duì)于多個(gè)客戶端連接并不存在競(jìng)爭(zhēng),利用setnx實(shí)現(xiàn)鎖。
8.Redis是使用c語(yǔ)言開(kāi)發(fā)的。
9.Redis前端啟動(dòng)命令
./redis-server
10.Reids支持的語(yǔ)言:
java、C、C#、C++、php、Node.js、Go等。
11.Redis 持久化方案:
Rdb 和 Aof
12.Redis 的主從復(fù)制
持久化保證了即使redis服務(wù)重啟也不會(huì)丟失數(shù)據(jù),因?yàn)閞edis服務(wù)重啟后會(huì)將硬盤(pán)上持久化的數(shù)據(jù)恢復(fù)到內(nèi)存中,但是當(dāng)redis服務(wù)器的硬盤(pán)損壞了可能會(huì)導(dǎo)致數(shù)據(jù)丟失,如果通過(guò)redis的主從復(fù)制機(jī)制就可以避免這種單點(diǎn)故障,
13.Redis是單線程的,但Redis為什么這么快?
1、完全基于內(nèi)存,絕大部分請(qǐng)求是純粹的內(nèi)存操作,非常快速。數(shù)據(jù)存在內(nèi)存中,類似于HashMap,HashMap的優(yōu)勢(shì)就是查找和操作的時(shí)間復(fù)雜度都是O(1);
2、數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單,對(duì)數(shù)據(jù)操作也簡(jiǎn)單,Redis中的數(shù)據(jù)結(jié)構(gòu)是專門進(jìn)行設(shè)計(jì)的;
3、采用單線程,避免了不必要的上下文切換和競(jìng)爭(zhēng)條件,也不存在多進(jìn)程或者多線程導(dǎo)致的切換而消耗 CPU,不用去考慮各種鎖的問(wèn)題,不存在加鎖釋放鎖操作,沒(méi)有因?yàn)榭赡艹霈F(xiàn)死鎖而導(dǎo)致的性能消耗;
4、使用多路I/O復(fù)用模型,非阻塞IO;這里“多路”指的是多個(gè)網(wǎng)絡(luò)連接,“復(fù)用”指的是復(fù)用同一個(gè)線程
5、使用底層模型不同,它們之間底層實(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í)間去移動(dòng)和請(qǐng)求;
14.為什么Redis是單線程的?
Redis是基于內(nèi)存的操作,CPU不是Redis的瓶頸,Redis的瓶頸最有可能是機(jī)器內(nèi)存的大小或者網(wǎng)絡(luò)帶寬。既然單線程容易實(shí)現(xiàn),而且CPU不會(huì)成為瓶頸,那就順理成章地采用單線程的方案了(畢竟采用多線程會(huì)有很多麻煩!)。
15.Redis info查看命令:info memory
16.Redis內(nèi)存模型
used_memory:Redis分配器分配的內(nèi)存總量(單位是字節(jié)),包括使用的虛擬內(nèi)存(即swap);Redis分配器后面會(huì)介紹。used_memory_human只是顯示更友好。
used_memory_rss**:**Redis進(jìn)程占據(jù)操作系統(tǒng)的內(nèi)存(單位是字節(jié)),與top及ps命令看到的值是一致的;除了分配器分配的內(nèi)存之外,used_memory_rss還包括進(jìn)程運(yùn)行本身需要的內(nèi)存、內(nèi)存碎片等,但是不包括虛擬內(nèi)存。
mem_fragmentation_ratio**:**內(nèi)存碎片比率,該值是used_memory_rss / used_memory的比值。
mem_allocator**:**Redis使用的內(nèi)存分配器,在編譯時(shí)指定;可以是 libc 、jemalloc或者tcmalloc,默認(rèn)是jemalloc;截圖中使用的便是默認(rèn)的jemalloc。
17.Redis內(nèi)存劃分
數(shù)據(jù)
作為數(shù)據(jù)庫(kù),數(shù)據(jù)是最主要的部分;這部分占用的內(nèi)存會(huì)統(tǒng)計(jì)在used_memory中。
進(jìn)程本身運(yùn)行需要的內(nèi)存
Redis主進(jìn)程本身運(yùn)行肯定需要占用內(nèi)存,如代碼、常量池等等;這部分內(nèi)存大約幾兆,在大多數(shù)生產(chǎn)環(huán)境中與Redis數(shù)據(jù)占用的內(nèi)存相比可以忽略。這部分內(nèi)存不是由jemalloc分配,因此不會(huì)統(tǒng)計(jì)在used_memory中。
緩沖內(nèi)存
緩沖內(nèi)存包括客戶端緩沖區(qū)、復(fù)制積壓緩沖區(qū)、AOF緩沖區(qū)等;其中,客戶端緩沖存儲(chǔ)客戶端連接的輸入輸出緩沖;復(fù)制積壓緩沖用于部分復(fù)制功能;AOF緩沖區(qū)用于在進(jìn)行AOF重寫(xiě)時(shí),保存最近的寫(xiě)入命令。在了解相應(yīng)功能之前,不需要知道這些緩沖的細(xì)節(jié);這部分內(nèi)存由jemalloc分配,因此會(huì)統(tǒng)計(jì)在used_memory中。
內(nèi)存碎片
內(nèi)存碎片是Redis在分配、回收物理內(nèi)存過(guò)程中產(chǎn)生的。例如,如果對(duì)數(shù)據(jù)的更改頻繁,而且數(shù)據(jù)之間的大小相差很大,可能導(dǎo)致redis釋放的空間在物理內(nèi)存中并沒(méi)有釋放,但redis又無(wú)法有效利用,這就形成了內(nèi)存碎片。內(nèi)存碎片不會(huì)統(tǒng)計(jì)在used_memory中。
18.Redis對(duì)象有5種類型
無(wú)論是哪種類型,Redis都不會(huì)直接存儲(chǔ),而是通過(guò)redisObject對(duì)象進(jìn)行存儲(chǔ)。
19.Redis沒(méi)有直接使用C字符串
(即以空字符’\0’結(jié)尾的字符數(shù)組)作為默認(rèn)的字符串表示,而是使用了SDS。SDS是簡(jiǎn)單動(dòng)態(tài)字符串(Simple Dynamic String)的縮寫(xiě)。
20.Reidis的SDS在C字符串的基礎(chǔ)上加入了free和len字段
21.Reids主從復(fù)制
復(fù)制是高可用Redis的基礎(chǔ),哨兵和集群都是在復(fù)制基礎(chǔ)上實(shí)現(xiàn)高可用的。復(fù)制主要實(shí)現(xiàn)了數(shù)據(jù)的多機(jī)備份,以及對(duì)于讀操作的負(fù)載均衡和簡(jiǎn)單的故障恢復(fù)。缺陷:故障恢復(fù)無(wú)法自動(dòng)化;寫(xiě)操作無(wú)法負(fù)載均衡;存儲(chǔ)能力受到單機(jī)的限制。
22.Redis哨兵
在復(fù)制的基礎(chǔ)上,哨兵實(shí)現(xiàn)了自動(dòng)化的故障恢復(fù)。缺陷:寫(xiě)操作無(wú)法負(fù)載均衡;存儲(chǔ)能力受到單機(jī)的限制。
23.Reids持久化觸發(fā)條件
RDB持久化的觸發(fā)分為手動(dòng)觸發(fā)和自動(dòng)觸發(fā)兩種。
24.Redis 開(kāi)啟AOF
Redis服務(wù)器默認(rèn)開(kāi)啟RDB,關(guān)閉AOF;要開(kāi)啟AOF,需要在配置文件中配置:
appendonly yes
25.AOF常用配置總結(jié)
下面是AOF常用的配置項(xiàng),以及默認(rèn)值;前面介紹過(guò)的這里不再詳細(xì)介紹。
-
appendonly no:是否開(kāi)啟AOF
-
appendfilename "appendonly.aof":AOF文件名
-
dir ./:RDB文件和AOF文件所在目錄
-
appendfsync everysec:fsync持久化策略
-
no-appendfsync-on-rewrite no:AOF重寫(xiě)期間是否禁止fsync;如果開(kāi)啟該選項(xiàng),可以減輕文件重寫(xiě)時(shí)CPU和硬盤(pán)的負(fù)載(尤其是硬盤(pán)),但是可能會(huì)丟失AOF重寫(xiě)期間的數(shù)據(jù);需要在負(fù)載和安全性之間進(jìn)行平衡
-
auto-aof-rewrite-percentage 100:文件重寫(xiě)觸發(fā)條件之一
-
auto-aof-rewrite-min-size 64mb:文件重寫(xiě)觸發(fā)提交之一
-
aof-load-truncated yes:如果AOF文件結(jié)尾損壞,Redis啟動(dòng)時(shí)是否仍載入AOF文件
26.RDB和AOF的優(yōu)缺點(diǎn)
RDB持久化
優(yōu)點(diǎn):RDB文件緊湊,體積小,網(wǎng)絡(luò)傳輸快,適合全量復(fù)制;恢復(fù)速度比AOF快很多。當(dāng)然,與AOF相比,RDB最重要的優(yōu)點(diǎn)之一是對(duì)性能的影響相對(duì)較小。
缺點(diǎn):RDB文件的致命缺點(diǎn)在于其數(shù)據(jù)快照的持久化方式?jīng)Q定了必然做不到實(shí)時(shí)持久化,而在數(shù)據(jù)越來(lái)越重要的今天,數(shù)據(jù)的大量丟失很多時(shí)候是無(wú)法接受的,因此AOF持久化成為主流。此外,RDB文件需要滿足特定格式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。
AOF持久化
與RDB持久化相對(duì)應(yīng),AOF的優(yōu)點(diǎn)在于支持秒級(jí)持久化、兼容性好,缺點(diǎn)是文件大、恢復(fù)速度慢、對(duì)性能影響大。
27.持久化策略選擇
(1)如果Redis中的數(shù)據(jù)完全丟棄也沒(méi)有關(guān)系(如Redis完全用作DB層數(shù)據(jù)的cache),那么無(wú)論是單機(jī),還是主從架構(gòu),都可以不進(jìn)行任何持久化。
(2)在單機(jī)環(huán)境下(對(duì)于個(gè)人開(kāi)發(fā)者,這種情況可能比較常見(jiàn)),如果可以接受十幾分鐘或更多的數(shù)據(jù)丟失,選擇RDB對(duì)Redis的性能更加有利;如果只能接受秒級(jí)別的數(shù)據(jù)丟失,應(yīng)該選擇AOF。
(3)但在多數(shù)情況下,我們都會(huì)配置主從環(huán)境,slave的存在既可以實(shí)現(xiàn)數(shù)據(jù)的熱備,也可以進(jìn)行讀寫(xiě)分離分擔(dān)Redis讀請(qǐng)求,以及在master宕掉后繼續(xù)提供服務(wù)。
28.redis緩存被擊穿處理機(jī)制
使用mutex。簡(jiǎn)單地來(lái)說(shuō),就是在緩存失效的時(shí)候(判斷拿出來(lái)的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者M(jìn)emcache的ADD)去set一個(gè)mutex key,當(dāng)操作返回成功時(shí),再進(jìn)行l(wèi)oad db的操作并回設(shè)緩存;否則,就重試整個(gè)get緩存的方法
29.Redis還提供的高級(jí)工具
像慢查詢分析、性能測(cè)試、Pipeline、事務(wù)、Lua自定義命令、Bitmaps、HyperLogLog、發(fā)布/訂閱、Geo等個(gè)性化功能。
30.Redis常用管理命令
# dbsize 返回當(dāng)前數(shù)據(jù)庫(kù) key 的數(shù)量。 # info 返回當(dāng)前 redis 服務(wù)器狀態(tài)和一些統(tǒng)計(jì)信息。 # monitor 實(shí)時(shí)監(jiān)聽(tīng)并返回redis服務(wù)器接收到的所有請(qǐng)求信息。 # shutdown 把數(shù)據(jù)同步保存到磁盤(pán)上,并關(guān)閉redis服務(wù)。 # config get parameter 獲取一個(gè) redis 配置參數(shù)信息。(個(gè)別參數(shù)可能無(wú)法獲取) # config set parameter value 設(shè)置一個(gè) redis 配置參數(shù)信息。(個(gè)別參數(shù)可能無(wú)法獲取) # config resetstat 重置 info 命令的統(tǒng)計(jì)信息。(重置包括:keyspace 命中數(shù)、 # keyspace 錯(cuò)誤數(shù)、 處理命令數(shù),接收連接數(shù)、過(guò)期 key 數(shù)) # debug object key 獲取一個(gè) key 的調(diào)試信息。 # debug segfault 制造一次服務(wù)器當(dāng)機(jī)。 # flushdb 刪除當(dāng)前數(shù)據(jù)庫(kù)中所有 key,此方法不會(huì)失敗。小心慎用 # flushall 刪除全部數(shù)據(jù)庫(kù)中所有 key,此方法不會(huì)失敗。小心慎用31.Reids工具命令
#redis-server:Redis 服務(wù)器的 daemon 啟動(dòng)程序 #redis-cli:Redis 命令行操作工具。當(dāng)然,你也可以用 telnet 根據(jù)其純文本協(xié)議來(lái)操作 #redis-benchmark:Redis 性能測(cè)試工具,測(cè)試 Redis 在你的系統(tǒng)及你的配置下的讀寫(xiě)性能 $redis-benchmark -n 100000 –c 50 #模擬同時(shí)由 50 個(gè)客戶端發(fā)送 100000 個(gè) SETs/GETs 查詢 #redis-check-aof:更新日志檢查 #redis-check-dump:本地?cái)?shù)據(jù)庫(kù)檢查32.為什么需要持久化?
由于Redis是一種內(nèi)存型數(shù)據(jù)庫(kù),即服務(wù)器在運(yùn)行時(shí),系統(tǒng)為其分配了一部分內(nèi)存存儲(chǔ)數(shù)據(jù),一旦服務(wù)器掛了,或者突然宕機(jī)了,那么數(shù)據(jù)庫(kù)里面的數(shù)據(jù)將會(huì)丟失,為了使服務(wù)器即使突然關(guān)機(jī)也能保存數(shù)據(jù),必須通過(guò)持久化的方式將數(shù)據(jù)從內(nèi)存保存到磁盤(pán)中。
33.判斷key是否存在
exists key +key名字
34.刪除key
del key1 key2 ...35.緩存和數(shù)據(jù)庫(kù)間數(shù)據(jù)一致性問(wèn)題
分布式環(huán)境下(單機(jī)就不用說(shuō)了)非常容易出現(xiàn)緩存和數(shù)據(jù)庫(kù)間的數(shù)據(jù)一致性問(wèn)題,針對(duì)這一點(diǎn)的話,只能說(shuō),如果你的項(xiàng)目對(duì)緩存的要求是強(qiáng)一致性的,那么請(qǐng)不要使用緩存。我們只能采取合適的策略來(lái)降低緩存和數(shù)據(jù)庫(kù)間數(shù)據(jù)不一致的概率,而無(wú)法保證兩者間的強(qiáng)一致性。合適的策略包括 合適的緩存更新策略,更新數(shù)據(jù)庫(kù)后要及時(shí)更新緩存、緩存失敗時(shí)增加重試機(jī)制,例如MQ模式的消息隊(duì)列。
36.布隆過(guò)濾器
bloomfilter就類似于一個(gè)hash set,用于快速判某個(gè)元素是否存在于集合中,其典型的應(yīng)用場(chǎng)景就是快速判斷一個(gè)key是否存在于某容器,不存在就直接返回。布隆過(guò)濾器的關(guān)鍵就在于hash算法和容器大小
37.緩存雪崩問(wèn)題
存在同一時(shí)間內(nèi)大量鍵過(guò)期(失效),接著來(lái)的一大波請(qǐng)求瞬間都落在了數(shù)據(jù)庫(kù)中導(dǎo)致連接異常。
解決方案:
1、也是像解決緩存穿透一樣加鎖排隊(duì)。
2、建立備份緩存,緩存A和緩存B,A設(shè)置超時(shí)時(shí)間,B不設(shè)值超時(shí)時(shí)間,先從A讀緩存,A沒(méi)有讀B,并且更新A緩存和B緩存;
38.緩存并發(fā)問(wèn)題
這里的并發(fā)指的是多個(gè)redis的client同時(shí)set key引起的并發(fā)問(wèn)題。比較有效的解決方案就是把redis.set操作放在隊(duì)列中使其串行化,必須的一個(gè)一個(gè)執(zhí)行,具體的代碼就不上了,當(dāng)然加鎖也是可以的,至于為什么不用redis中的事務(wù),留給各位看官自己思考探究。
39.Redis分布式
redis支持主從的模式。原則:Master會(huì)將數(shù)據(jù)同步到slave,而slave不會(huì)將數(shù)據(jù)同步到master。Slave啟動(dòng)時(shí)會(huì)連接master來(lái)同步數(shù)據(jù)。
這是一個(gè)典型的分布式讀寫(xiě)分離模型。我們可以利用master來(lái)插入數(shù)據(jù),slave提供檢索服務(wù)。這樣可以有效減少單個(gè)機(jī)器的并發(fā)訪問(wèn)數(shù)量
40.讀寫(xiě)分離模型
通過(guò)增加Slave DB的數(shù)量,讀的性能可以線性增長(zhǎng)。為了避免Master DB的單點(diǎn)故障,集群一般都會(huì)采用兩臺(tái)Master DB做雙機(jī)熱備,所以整個(gè)集群的讀和寫(xiě)的可用性都非常高。讀寫(xiě)分離架構(gòu)的缺陷在于,不管是Master還是Slave,每個(gè)節(jié)點(diǎn)都必須保存完整的數(shù)據(jù),如果在數(shù)據(jù)量很大的情況下,集群的擴(kuò)展能力還是受限于單個(gè)節(jié)點(diǎn)的存儲(chǔ)能力,而且對(duì)于Write-intensive類型的應(yīng)用,讀寫(xiě)分離架構(gòu)并不適合。
41.數(shù)據(jù)分片模型
為了解決讀寫(xiě)分離模型的缺陷,可以將數(shù)據(jù)分片模型應(yīng)用進(jìn)來(lái)。
可以將每個(gè)節(jié)點(diǎn)看成都是獨(dú)立的master,然后通過(guò)業(yè)務(wù)實(shí)現(xiàn)數(shù)據(jù)分片。
結(jié)合上面兩種模型,可以將每個(gè)master設(shè)計(jì)成由一個(gè)master和多個(gè)slave組成的模型。
42. redis常見(jiàn)性能問(wèn)題和解決方案:
Master最好不要做任何持久化工作,如RDB內(nèi)存快照和AOF日志文件
如果數(shù)據(jù)比較重要,某個(gè)Slave開(kāi)啟AOF備份數(shù)據(jù),策略設(shè)置為每秒同步一次
為了主從復(fù)制的速度和連接的穩(wěn)定性,Master和Slave最好在同一個(gè)局域網(wǎng)內(nèi)
盡量避免在壓力很大的主庫(kù)上增加從庫(kù)
43.redis通訊協(xié)議
RESP 是redis客戶端和服務(wù)端之前使用的一種通訊協(xié)議;RESP 的特點(diǎn):實(shí)現(xiàn)簡(jiǎn)單、快速解析、可讀性好
44.Redis分布式鎖實(shí)現(xiàn)
先拿setnx來(lái)爭(zhēng)搶鎖,搶到之后,再用expire給鎖加一個(gè)過(guò)期時(shí)間防止鎖忘記了釋放。**如果在setnx之后執(zhí)行expire之前進(jìn)程意外crash或者要重啟維護(hù)了,那會(huì)怎么樣?**set指令有非常復(fù)雜的參數(shù),這個(gè)應(yīng)該是可以同時(shí)把setnx和expire合成一條指令來(lái)用的!
45.Redis做異步隊(duì)列
一般使用list結(jié)構(gòu)作為隊(duì)列,rpush生產(chǎn)消息,lpop消費(fèi)消息。當(dāng)lpop沒(méi)有消息的時(shí)候,要適當(dāng)sleep一會(huì)再重試。缺點(diǎn):在消費(fèi)者下線的情況下,生產(chǎn)的消息會(huì)丟失,得使用專業(yè)的消息隊(duì)列如rabbitmq等。**能不能生產(chǎn)一次消費(fèi)多次呢?**使用pub/sub主題訂閱者模式,可以實(shí)現(xiàn)1:N的消息隊(duì)列。
46.Redis中海量數(shù)據(jù)的正確操作方式
利用SCAN系列命令(SCAN、SSCAN、HSCAN、ZSCAN)完成數(shù)據(jù)迭代。
47.SCAN系列命令注意事項(xiàng)
-
SCAN的參數(shù)沒(méi)有key,因?yàn)槠涞鷮?duì)象是DB內(nèi)數(shù)據(jù);
-
返回值都是數(shù)組,第一個(gè)值都是下一次迭代游標(biāo);
-
時(shí)間復(fù)雜度:每次請(qǐng)求都是O(1),完成所有迭代需要O(N),N是元素?cái)?shù)量;
-
可用版本:version >= 2.8.0;
48.Redis 管道 Pipeline
在某些場(chǎng)景下我們?cè)?strong>一次操作中可能需要執(zhí)行多個(gè)命令,而如果我們只是一個(gè)命令一個(gè)命令去執(zhí)行則會(huì)浪費(fèi)很多網(wǎng)絡(luò)消耗時(shí)間,如果將命令一次性傳輸?shù)?Redis中去再執(zhí)行,則會(huì)減少很多開(kāi)銷時(shí)間。但是需要注意的是?pipeline中的命令并不是原子性執(zhí)行的,也就是說(shuō)管道中的命令到達(dá)?Redis服務(wù)器的時(shí)候可能會(huì)被其他的命令穿插
49.事務(wù)不支持回滾
50.手寫(xiě)一個(gè) LRU 算法
class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int CACHE_SIZE;/*** 傳遞進(jìn)來(lái)最多能緩存多少數(shù)據(jù)** @param cacheSize 緩存大小*/public LRUCache(int cacheSize) {// true 表示讓 linkedHashMap 按照訪問(wèn)順序來(lái)進(jìn)行排序,最近訪問(wèn)的放在頭部,最老訪問(wèn)的放在尾部。super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);CACHE_SIZE = cacheSize;}@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {// 當(dāng) map中的數(shù)據(jù)量大于指定的緩存?zhèn)€數(shù)的時(shí)候,就自動(dòng)刪除最老的數(shù)據(jù)。return size() > CACHE_SIZE;} }51.多節(jié)點(diǎn) Redis 分布式鎖:Redlock 算法
獲取當(dāng)前時(shí)間(start)。
依次向 N 個(gè)?Redis節(jié)點(diǎn)請(qǐng)求鎖。請(qǐng)求鎖的方式與從單節(jié)點(diǎn)?Redis獲取鎖的方式一致。為了保證在某個(gè)?Redis節(jié)點(diǎn)不可用時(shí)該算法能夠繼續(xù)運(yùn)行,獲取鎖的操作都需要設(shè)置超時(shí)時(shí)間,需要保證該超時(shí)時(shí)間遠(yuǎn)小于鎖的有效時(shí)間。這樣才能保證客戶端在向某個(gè)?Redis節(jié)點(diǎn)獲取鎖失敗之后,可以立刻嘗試下一個(gè)節(jié)點(diǎn)。
計(jì)算獲取鎖的過(guò)程總共消耗多長(zhǎng)時(shí)間(consumeTime = end - start)。如果客戶端從大多數(shù)?Redis節(jié)點(diǎn)(>= N/2 + 1) 成功獲取鎖,并且獲取鎖總時(shí)長(zhǎng)沒(méi)有超過(guò)鎖的有效時(shí)間,這種情況下,客戶端會(huì)認(rèn)為獲取鎖成功,否則,獲取鎖失敗。
如果最終獲取鎖成功,鎖的有效時(shí)間應(yīng)該重新設(shè)置為鎖最初的有效時(shí)間減去?consumeTime。
如果最終獲取鎖失敗,客戶端應(yīng)該立刻向所有?Redis節(jié)點(diǎn)發(fā)起釋放鎖的請(qǐng)求。
52.Redis 中設(shè)置過(guò)期時(shí)間主要通過(guò)以下四種方式
-
expire key seconds:設(shè)置 key 在 n 秒后過(guò)期;
-
pexpire key milliseconds:設(shè)置 key 在 n 毫秒后過(guò)期;
-
expireat key timestamp:設(shè)置 key 在某個(gè)時(shí)間戳(精確到秒)之后過(guò)期;
-
pexpireat key millisecondsTimestamp:設(shè)置 key 在某個(gè)時(shí)間戳(精確到毫秒)之后過(guò)期;
53.Reids三種不同刪除策略
定時(shí)刪除:在設(shè)置鍵的過(guò)期時(shí)間的同時(shí),創(chuàng)建一個(gè)定時(shí)任務(wù),當(dāng)鍵達(dá)到過(guò)期時(shí)間時(shí),立即執(zhí)行對(duì)鍵的刪除操作
惰性刪除:放任鍵過(guò)期不管,但在每次從鍵空間獲取鍵時(shí),都檢查取得的鍵是否過(guò)期,如果過(guò)期的話,就刪除該鍵,如果沒(méi)有過(guò)期,就返回該鍵
定期刪除:每隔一點(diǎn)時(shí)間,程序就對(duì)數(shù)據(jù)庫(kù)進(jìn)行一次檢查,刪除里面的過(guò)期鍵,至于要?jiǎng)h除多少過(guò)期鍵,以及要檢查多少個(gè)數(shù)據(jù)庫(kù),則由算法決定。
54.定時(shí)刪除
-
**優(yōu)點(diǎn):**對(duì)內(nèi)存友好,定時(shí)刪除策略可以保證過(guò)期鍵會(huì)盡可能快地被刪除,并釋放國(guó)期間所占用的內(nèi)存
-
**缺點(diǎn):**對(duì)cpu時(shí)間不友好,在過(guò)期鍵比較多時(shí),刪除任務(wù)會(huì)占用很大一部分cpu時(shí)間,在內(nèi)存不緊張但cpu時(shí)間緊張的情況下,將cpu時(shí)間用在刪除和當(dāng)前任務(wù)無(wú)關(guān)的過(guò)期鍵上,影響服務(wù)器的響應(yīng)時(shí)間和吞吐量
55.定期刪除
由于定時(shí)刪除會(huì)占用太多cpu時(shí)間,影響服務(wù)器的響應(yīng)時(shí)間和吞吐量以及惰性刪除浪費(fèi)太多內(nèi)存,有內(nèi)存泄露的危險(xiǎn),所以出現(xiàn)一種整合和折中這兩種策略的定期刪除策略。
定期刪除策略每隔一段時(shí)間執(zhí)行一次刪除過(guò)期鍵操作,并通過(guò)限制刪除操作執(zhí)行的時(shí)長(zhǎng)和頻率來(lái)減少刪除操作對(duì)CPU時(shí)間的影響。
定時(shí)刪除策略有效地減少了因?yàn)檫^(guò)期鍵帶來(lái)的內(nèi)存浪費(fèi)。
56.惰性刪除
-
**優(yōu)點(diǎn):**對(duì)cpu時(shí)間友好,在每次從鍵空間獲取鍵時(shí)進(jìn)行過(guò)期鍵檢查并是否刪除,刪除目標(biāo)也僅限當(dāng)前處理的鍵,這個(gè)策略不會(huì)在其他無(wú)關(guān)的刪除任務(wù)上花費(fèi)任何cpu時(shí)間。
-
**缺點(diǎn):**對(duì)內(nèi)存不友好,過(guò)期鍵過(guò)期也可能不會(huì)被刪除,導(dǎo)致所占的內(nèi)存也不會(huì)釋放。甚至可能會(huì)出現(xiàn)內(nèi)存泄露的現(xiàn)象,當(dāng)存在很多過(guò)期鍵,而這些過(guò)期鍵又沒(méi)有被訪問(wèn)到,這會(huì)可能導(dǎo)致它們會(huì)一直保存在內(nèi)存中,造成內(nèi)存泄露。
57.Reids 管理工具:Redis Manager 2.0
github地址
58.Redis常見(jiàn)的幾種緩存策略
-
Cache-Aside
-
Read-Through
-
Write-Through
-
Write-Behind
59.Redis Module 實(shí)現(xiàn)布隆過(guò)濾器
Redis module 是Redis 4.0 以后支持的新的特性,這里很多國(guó)外牛逼的大學(xué)和機(jī)構(gòu)提供了很多牛逼的Module 只要編譯引入到Redis 中就能輕松的實(shí)現(xiàn)我們某些需求的功能。在Redis 官方Module 中有一些我們常見(jiàn)的一些模塊,我們?cè)谶@里就做一個(gè)簡(jiǎn)單的使用。
-
neural-redis 主要是神經(jīng)網(wǎng)絡(luò)的機(jī)器學(xué),集成到redis 可以做一些機(jī)器訓(xùn)練感興趣的可以嘗試
-
RedisSearch 主要支持一些富文本的的搜索
-
RedisBloom 支持分布式環(huán)境下的Bloom 過(guò)濾器
60.Redis 到底是怎么實(shí)現(xiàn)“附近的人”
使用方式
GEOADD key longitude latitude member [longitude latitude member ...]將給定的位置對(duì)象(緯度、經(jīng)度、名字)添加到指定的key。其中,key為集合名稱,member為該經(jīng)緯度所對(duì)應(yīng)的對(duì)象。在實(shí)際運(yùn)用中,當(dāng)所需存儲(chǔ)的對(duì)象數(shù)量過(guò)多時(shí),可通過(guò)設(shè)置多key(如一個(gè)省一個(gè)key)的方式對(duì)對(duì)象集合變相做sharding,避免單集合數(shù)量過(guò)多。
成功插入后的返回值:
(integer) N其中N為成功插入的個(gè)數(shù)。
轉(zhuǎn)自:
https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzIxMTE0ODU5NQ==&scene=124#wechat_redirect
總結(jié)
以上是生活随笔為你收集整理的大剑无锋之Redis面试题【推荐】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Google布隆过滤器与Redis布隆过
- 下一篇: 大剑无锋之Hbase的优化【面试推荐】