更新時(shí)間:2022-12-22 15:40:36 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1495次
redis有著出色的高性能與并發(fā),是在大流量的網(wǎng)站中,需要我們用到的緩存技術(shù),如果大家想要在面試官面前有很好的表現(xiàn),那么redis的技術(shù)肯定是需要掌握的。今天小編就針對redis的面試題,整理出了比較常見的,希望可以幫助到大家:
一、Redis到底是單線程還是多線程
Redis 6.0版本之前的單線程指的是其網(wǎng)絡(luò)I/O和鍵值對讀寫是由一個(gè)線程完成。
也就是只有網(wǎng)絡(luò)請求模塊和數(shù)據(jù)操作模塊是單線程的,而其他的持久化、集群數(shù)據(jù)同步等,其實(shí)是由額外的線程執(zhí)行的。
Redis6.0引入的多線程指的是網(wǎng)絡(luò)請求過程采用了多線程,但鍵值對讀寫命令仍然是單線程處理的,所以Redis依然是并發(fā)安全的。
二、Redis單線程為什么還能這么快
命令執(zhí)行是基于內(nèi)存操作的,一天命令在內(nèi)存里操作的時(shí)間是幾十納秒
命令執(zhí)行是單線程操作,沒有線程切換開銷。
基于IO多路復(fù)用機(jī)制提升Redis的IO利用率。
高效的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu):全局hash表以及多種高效的數(shù)據(jù)結(jié)構(gòu),比如:跳表、壓縮列表、鏈表等。
三、Redis底層數(shù)據(jù)是如何用跳表來存儲(chǔ)的
四、Redis key 過期了為什么內(nèi)存沒釋放
如果原本這個(gè)key是有過期時(shí)間的,再給這個(gè)key使用SET命令并且不設(shè)置過期時(shí)間,那么Redis會(huì)自動(dòng)擦除這個(gè)key的過期時(shí)間。
Redis對于過期的key的處理一般有惰性刪除和定時(shí)刪除兩種策略
惰性刪除:當(dāng)讀/寫一個(gè)已經(jīng)過期的key時(shí),會(huì)觸發(fā)惰性刪除策略,判斷key是否過期,如果過期了直接刪除這個(gè)key。這也是key過期了為什么沒有立即釋放內(nèi)存。
定時(shí)刪除:由于惰性刪除無法保證冷數(shù)據(jù)被及時(shí)刪掉,所以Redis會(huì)定期(默認(rèn)每100ms)主動(dòng)淘汰一批已過期的key,這里的一批只是部分過期的key,所以可能會(huì)出現(xiàn)key已經(jīng)過期了但是還沒有被清理掉的情況,導(dǎo)致內(nèi)存沒有釋放。
五、Redis key沒有設(shè)置過期時(shí)間為什么被Redis主動(dòng)刪除了
當(dāng)Redis已用內(nèi)存超過maxmemory限定時(shí),廚房主動(dòng)清理策略
主動(dòng)清理策略在Redis4.0之前,實(shí)現(xiàn)了6種內(nèi)存淘汰策略,在4.0之后,又增加了兩種,總共8種:
no-eviction | 當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),新寫入操作會(huì)報(bào)錯(cuò),無法寫入新數(shù)據(jù),一般不采用。 |
allkeys-Iru | 當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),移除最近最少使用的key,這個(gè)是最常用的 |
allkeys-random | 當(dāng)內(nèi)存不足以容納新寫入的數(shù)據(jù)時(shí),隨機(jī)移除key |
allkeys-Ifu | 當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),移除最不經(jīng)常(最少) 使用的key |
volatile-lru | 當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在設(shè)置了過期時(shí)間的key中,移除最近最少使用的key。 |
volatile- random |
內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在設(shè)置了過期時(shí)間的key中,隨機(jī)移除某個(gè)key。 |
volatile-lfu | 當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在設(shè)置了過期時(shí)間的key中,移除最不經(jīng)常(最少)使用的key |
volatile-tt! | 當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),在設(shè)置了過期時(shí)間的key中,優(yōu)先移除過期時(shí)間最早(剩余存活時(shí)間最短)的key。 |
六、Redis 淘汰key的算法LRU與LFU的區(qū)別
LRU算法(Least Recently Used,最近最少使用):淘汰很久沒被訪問的數(shù)據(jù),以最近一次訪問時(shí)間作為參考。
LFU算法(Least Frequently Used,最不經(jīng)常使用):淘汰最近一段時(shí)間被訪問次數(shù)最少的數(shù)據(jù),以次數(shù)作為參考。
絕大多數(shù)情況我們可以用LRU策略,當(dāng)存在大量的熱點(diǎn)緩存數(shù)據(jù)時(shí),LFU可能更好一點(diǎn)。
七、刪除Key命令會(huì)阻塞Redis嘛
會(huì)阻塞的。DEL key[key...] 命令會(huì)根據(jù)key類型來刪除,時(shí)間復(fù)雜度也是不一樣的,O(N),N為被刪除的key數(shù)量
刪除單個(gè)字符串類型的key,時(shí)間復(fù)雜度為O(1)
刪除單個(gè)列表、集合、有序集合或哈希類型的key,時(shí)間復(fù)雜度為O(M),M為以上數(shù)據(jù)結(jié)構(gòu)內(nèi)的元素?cái)?shù)量。
八、談?wù)凴edis集群數(shù)據(jù)hash分片算法
Redis 集群將所有數(shù)據(jù)劃分16384個(gè)slots,每個(gè)節(jié)點(diǎn)負(fù)責(zé)其中一部分槽位。當(dāng)Redis 集群的客戶端來連接集群時(shí),它也會(huì)得到一份集群的槽位信息并將其緩存到客戶端本地,這樣當(dāng)客戶端要查找某個(gè)key時(shí),可以根據(jù)槽位定位算法定位到目標(biāo)節(jié)點(diǎn)。
槽位定位算法
集群默認(rèn)會(huì)對key值使用crc16算法進(jìn)行hash,得到一個(gè)整數(shù)值,然后這個(gè)整數(shù)值對16384進(jìn)行取模運(yùn)算來得到具體的槽位。
Hash_slot = CRC16(key)mod13684
再根據(jù)槽位和節(jié)點(diǎn)的對應(yīng)關(guān)系就可以定位到key具體是在那個(gè)Redis節(jié)點(diǎn)上。
九、Redis執(zhí)行命令竟然有死循環(huán)阻塞Bug
Redis有個(gè)RANDOMKEY命令可以從Redis中隨機(jī)取出一個(gè)key,這個(gè)命令可能導(dǎo)致Redis死循環(huán)阻塞。
RANDOMKEY在隨機(jī)拿出一個(gè)key之后,首先會(huì)檢驗(yàn)這個(gè)key是否過期,如果該key過期,那么Redis會(huì)刪除它,這個(gè)過程就是惰性刪除,但是清理完了之后還不能結(jié)束,Redis會(huì)再找出一個(gè)沒過期的key返回給客戶端。
此時(shí),Redis則會(huì)繼續(xù)隨機(jī)拿出一個(gè)key,然后再判斷它是否過期,直到找到一個(gè)沒過期的key返回給客戶端。
這里就有一個(gè)問題,如果此時(shí)Redis中有大量的key過期,但還未來得及被清理掉,這個(gè)循環(huán)就會(huì)持續(xù)很久才能結(jié)束,這樣就會(huì)導(dǎo)致RANDOMKEY命令執(zhí)行耗時(shí)變長,影響Redis性能。
以上流程,其實(shí)是master上執(zhí)行的。如果在slave上執(zhí)行RANDOMKEY,那么問題更嚴(yán)重。
slave是不會(huì)自己清理過期的key,當(dāng)一個(gè)key要過期時(shí),master會(huì)先清理刪除它,之后master向slave發(fā)送一個(gè)DEL命令,告知slave也刪除這個(gè)key,以此達(dá)到主從一致。
假設(shè)Redis中存在大量已過期還未來得及清理的key,那么在slave上執(zhí)行RANDOMKEY時(shí),就會(huì)發(fā)生一下問題:
1、slave隨機(jī)取出一個(gè)key,判斷是否已經(jīng)過期。
2、key已經(jīng)過期,但是slave不會(huì)刪除它,而是繼續(xù)隨機(jī)尋找不過期的key
3、由于大量key都已過期,那slave就會(huì)找不到符合條件的key,就會(huì)進(jìn)入死循環(huán)。
這個(gè)Bug直到5.0才被修復(fù),修復(fù)方法就是在slave中設(shè)置一個(gè)最大查找次數(shù),無論找到與否,到了這個(gè)最大次數(shù)就退出循環(huán)。
十、一次線上事故,Redis主從切換導(dǎo)致了緩存雪崩
我們假設(shè),slave的機(jī)器時(shí)鐘比master走的快很多。
此時(shí),Redis master 里設(shè)置了過期時(shí)間的key,從slave角度來看,可能會(huì)有很多在master里沒過期,在slave里面已經(jīng)過期了的數(shù)據(jù)。
如果此時(shí)操作主從切換,把slave提升為新的master,新的master就會(huì)開始大量清理過期的key,此時(shí)就會(huì)導(dǎo)致以下結(jié)果:
1、master大量清理過期key,主線程可能會(huì)發(fā)生阻塞,無法及時(shí)處理客戶端請求。
2、Redis中數(shù)據(jù)大量過期,引發(fā)緩存雪崩。
所以,我們一定要保證主從庫的機(jī)器時(shí)鐘一致,避免發(fā)生這些問題。
以上就是“高頻出現(xiàn)的redis緩存面試題”,你能回答上來嗎?如果想要了解更多的Java面試題相關(guān)內(nèi)容,可以關(guān)注動(dòng)力節(jié)點(diǎn)Java官網(wǎng)。
相關(guān)閱讀