redis反杀面试官之10问
簡言
1. 筆者近兩年來一直使用redis,也對redis有過仔細(xì)的研究,不敢說精通,熟悉至少是有的
2. redis越來越火,網(wǎng)上相應(yīng)的文章,總結(jié),面試問題也有很多,但大多是應(yīng)付簡單面試用的,如果面試官再深入一些,恐怕大多數(shù)人都hold不住
3. 所以特在這里總結(jié)了一些有難度的問題,若你能認(rèn)真學(xué)習(xí)研究,不但能大幅提高對redis的理解程度,反殺面試官也是輕輕松松
4. 問題不止10個,隨時想到隨時更新,有時間就會把答案補上來
問題1:持久化的混合存儲模式(前面RDB+后面AOF),它的實現(xiàn)原理和好處
答:
問題2:scan命令,第三個參數(shù)應(yīng)該怎么填
答:先看下scan命令的格式,第1個參數(shù)是下標(biāo),第2個參數(shù)是匹配模式,第三個參數(shù)是限制個數(shù)
1 2 3 SCAN cursor [MATCH pattern] [COUNT count]但是這個count限制并不是必定能起效,受多種因素影響,大致如下
1. 當(dāng)redis發(fā)現(xiàn)你用hscan,zscan,scan命令遍歷的對象是壓縮列表實現(xiàn)的,說明對象內(nèi)元素比較少,會全部遍歷篩選后返回
2. 如果你不傳count參數(shù),那么redis會默認(rèn)設(shè)置為10
3. redis是對數(shù)組里面單個下標(biāo)里面的元素遍歷,如果某個下標(biāo)里面符合match格式的元素很多,會超出count值,單個下標(biāo)遍歷完后才會判斷是否超出count值,所以可能已經(jīng)超過了count
4. 如果單次遍歷過程中耗時過長,為防止redis卡頓,即使符合條件的元素有很多,也會提前返回,此時個數(shù)會少于count值
綜上:具體使用時要根據(jù)你對結(jié)果值的處理操作(元素數(shù)據(jù)總體量大小,單個元素的操作耗時等)來決定一批篩選多少個元素,redis已經(jīng)為我們做好了防護
具體scan命令的實現(xiàn)原理可參考筆者的這篇博客redis的scan命令的源碼分析,實現(xiàn)原理_papaya的博客-CSDN博客
問題3:scan命令,返回的游標(biāo)值在redis中代表什么,是槽位嗎,這個槽位和redis集群的槽位概念有關(guān)系嗎
答:
問題4:scan命令,返回的key中,有一定概率會出現(xiàn)重復(fù)的情況,能說下到底什么情況下會出現(xiàn)重復(fù)嗎?為什么,這種重復(fù)能優(yōu)化嗎
答:redis縮容的時候會出現(xiàn),因為rehash采用高位加法,舉例:遍歷到下圖中的橙色下標(biāo)(110)時發(fā)生了縮容,前面的000,100,010都已經(jīng)遍歷過了,其中000,100節(jié)點會被rehash到新的00節(jié)點上,不會重復(fù)遍歷。但是010,110節(jié)點都會rehash到新的10下標(biāo)(第一行綠色的)上,那么010下標(biāo)上對應(yīng)的元素就會被重復(fù)遍歷
問題5:redis的讀寫分離模式中,因為主從同步需要時間,所以有一定概率會出現(xiàn)主redis剛剛寫入,從redis讀取不到進而認(rèn)為該key不存在的情況,如何優(yōu)化
答:
問題6:redis命令查看單個key的大小有哪些命令,哪些是準(zhǔn)確的,哪些是不準(zhǔn)確的,比如--bigkeys命令的原理
答:
問題7:redis集群選舉時是使用raft算法還是paxos算法,知道raft算法和paxos算法的區(qū)別嗎
答:
問題8:rehash為什么要用高位加法,而不是我們通常的低位加法,好處是什么
答:采用高位進位加法,無論是擴容還是縮容,rehash 后的槽位在遍歷順序上是相鄰的,這也是scan命令能保證全盤遍歷的精妙之處,詳見這篇博客:redis之rehash原理_papaya的博客-CSDN博客_redis rehash原理
問題9:redis對象中有個字段叫l(wèi)ru,只有24位,在LRU模式下,存儲的是最后一次訪問時間。由于只有24位,能表示的最大時間只有194天,超過194天的key怎么辦,如何才能計算出它真正的空閑時間?
答:代碼如下
// 計算對象的空閑時間,也就是沒有被訪問的時間,返回結(jié)果是毫秒 unsigned long long estimateObjectIdleTime(robj* o) {unsigned long long lruclock = LRU_CLOCK();// 獲取Redis時鐘,也就是server.lruclock的值,單位:秒if (lruclock >= o->lru){// 正常遞增時直接減即可(LRU_CLOCK_RESOLUTION的值默認(rèn)是1000)return (lruclock - o->lru) * LRU_CLOCK_RESOLUTION;}else{// 折返了,則加一輪最大值后再減(LRU_CLOCK_MAX表示一輪的最大值,即2^24 - 1)return (lruclock + LRU_CLOCK_MAX - 0->lru) * LRU_CLOCK_RESOLUTION;} }問題10:redis事務(wù)的watch有沒有ABA問題,是如何解決的?
答:沒有ABA問題。redis會為每個要監(jiān)聽的key維護一個監(jiān)聽的client列表,任何key發(fā)生變化時都會檢測一下是否是watch中的key。若是watch中的key,則把監(jiān)控這個key的所有client都標(biāo)記為REDIS_DIRTY_CAS,意思是為該client的所有CAS操作都“dirty”了。當(dāng)服務(wù)器收到該client的事務(wù)執(zhí)行命令(即exec命令時),會檢測是否有REDIS_DIRTY_CAS標(biāo)記,若有,則直接返回,不再執(zhí)行事務(wù)
詳細(xì)分析可以見筆者的這篇博客:
redis的watch沒有ABA的問題_papaya的博客-CSDN博客
問題11:布隆過濾器怎么刪除元素呢?
答:經(jīng)典的布隆過濾器不支持刪除元素
如果一定要刪除元素,業(yè)內(nèi)普遍有兩種做法
方法1:定時異步重建布隆過濾器,比如每隔3天把所有元素重新hash,建立新的布隆過濾器,重建完后再刪掉舊的布隆過濾器。
方法2:使用計數(shù)型的布隆過濾器。因為經(jīng)典的布隆過濾器的一個位只能為0或1,為1時不能記錄有多少個元素引用了該位,一旦刪除,數(shù)據(jù)就亂了。但計數(shù)型的布隆過濾器每個位是一個數(shù)字,記錄了有多少個元素引用了該位,刪除一個元素時只需對其hash對應(yīng)的位的數(shù)字進行減1即可。
問題12:一般情況下redis cluster中key和slot的映射是通過算法(原理:crc16(key)%16384)對應(yīng)的,知道如何強制把key映射到指定的slot呢?
答:鍵哈希標(biāo)簽原理,代碼如下
unsigned int keyHashSlot(char *key, int keylen) {undefined int s, e;// 找到 { 的indexfor (s = 0; s < keylen; s++){if (key[s] == '{') break;}// 沒找到就計算crc16()的值if (s == keylen) {return crc16(key,keylen) & 0x3FFF;}// 再往后面找 } 的indexfor (e = s+1; e < keylen; e++){if (key[e] == '}') break;}// 沒找到 } 或者{}之間為空,仍然計算crc16()的值if (e == keylen || e == s+1) {return crc16(key,keylen) & 0x3FFF;}// 獲取{}之間的字符串進行crc16()計算return crc16(key+s+1,e-s-1) & 0x3FFF; }總結(jié)
以上是生活随笔為你收集整理的redis反杀面试官之10问的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis中布隆过滤器的使用及原理
- 下一篇: redis之rehash原理