前言:目前Redis相關(guān)的知識內(nèi)容已經(jīng)成為后端面試的考核??土?,掌握并理解Redis可以為你的面試大大加分哦,另外想要在面試中脫穎而出,靠死記硬背標(biāo)準(zhǔn)答案是不可取的。在本系列中,小黑板將會以面試為導(dǎo)向,串聯(lián)起Redis的相關(guān)知識,幫助大家在面試中牢牢抓住面試官的小心心~

前情提要:在上篇文章中,我們討論了在面試中的Redis熱身問題(沒看過請點(diǎn)擊這里 Redis面試套路拆解(一),并且在文章末尾提到了Redis數(shù)據(jù)結(jié)構(gòu)的相關(guān)問題,那么我們就一起來看看面試官會從哪些角度提問,我們又該如何作答比較好呢?
話不多說,我們直接進(jìn)入正題!我們循序漸進(jìn)地模擬一下真實(shí)的面試場景,讀者朋友們也可以嘗試作答,看看面對面試官的“拷問”,你會給出怎樣的回答。
Q:你前面提到了Redis提供了比較豐富的數(shù)據(jù)結(jié)構(gòu)嘛,那你知道哪些數(shù)據(jù)結(jié)構(gòu)呢?
分析:其實(shí)Redis的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)(string、hash、list、set、 zset)大家肯定都會比較熟悉,但是如果僅僅只是回答這五種基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),而不了解高級數(shù)據(jù)結(jié)構(gòu)的話,那么在面試官這里評價(jià)肯定就很一般了。
所以我們還需要加上幾種高級數(shù)據(jù)結(jié)構(gòu),需要注意的是,你提到的東西一定要很了解才行,底層實(shí)現(xiàn)和原理都要掌握,并且能夠有條理的講清楚講明白,只有這樣才能讓面試官覺得眼前一亮~
A:Redis提供了非常豐富的數(shù)據(jù)類型,其中包括五種基礎(chǔ)的數(shù)據(jù)類型:string、hash、list、set、 zset,除此以外還提供了一些高級數(shù)據(jù)結(jié)構(gòu),比如:位圖(bitmap)、HyperLogLog和布隆過濾器(BloomFilter)等
分析:上面提到的點(diǎn)其實(shí)也會成為后續(xù)面試官深入的切入點(diǎn),在面試中面試官比較喜歡考察的數(shù)據(jù)結(jié)構(gòu)主要是string、zset、bitmap、hyperloglog以及布隆過濾器,這幾個(gè)是高頻考點(diǎn),掌握好這些數(shù)據(jù)結(jié)構(gòu),會成為面試中的加分項(xiàng),所以小黑板在Redis數(shù)據(jù)結(jié)構(gòu)篇也主要是圍繞這些高頻考點(diǎn)來做深入的,希望能幫到大家~
Q:那你詳細(xì)講講String類型吧?
分析:面試過程中,面試官基本上給的問題都不會特別具體,不會指明讓你具體回答哪一點(diǎn),這就需要我們自己去拓展,面試官也想看一看你對這個(gè)知識點(diǎn)究竟了解到什么程度,這是一個(gè)很好的展示機(jī)會,只要掌握好了就可以從容應(yīng)對。
涉及到String類型的問題,需要講清楚的點(diǎn)主要有幾個(gè)方面:
- 第一點(diǎn)是String類型的底層數(shù)據(jù)結(jié)構(gòu)
- 第二點(diǎn)是String類型的存儲方式
- 第三點(diǎn)是String類型的擴(kuò)容方式
A:首先是String類型的底層數(shù)據(jù)結(jié)構(gòu),redis中的String類型,實(shí)際上底層數(shù)據(jù)結(jié)構(gòu)是SDS,也就是簡單動態(tài)字符串(Simple Dynamic String),它是一個(gè)帶有長度信息的字節(jié)數(shù)組
struct SDS<T>{
T capacity; //數(shù)組容量,分配的容量
T len; //數(shù)組長度,實(shí)際的容量
byte flags; //標(biāo)志位
byte[] content; //數(shù)組內(nèi)容
}
其次是String類型的存儲方式,String有兩種存儲方式:embstr和raw
當(dāng)字符串長度比較短的時(shí)候使用embstr,長度超過44字節(jié)時(shí)使用raw方式存儲
注:之前沒有學(xué)過這方面內(nèi)容的小伙伴可能就會問了,什么是embstr,什么又是raw呢?有什么區(qū)別呢?為什么是44個(gè)字節(jié)呢?這其實(shí)也可能是面試官會深入的問題,在面試中講到你可以拓展的問題時(shí),可以主動詢問面試官是否需要深入講一下,是不錯(cuò)的加分項(xiàng)喲 ~
分析:embstr和raw實(shí)際上就是兩種不同的內(nèi)存分配方式,不過在了解這個(gè)知識之前,我們還需要知道一些預(yù)備知識:Redis對象頭
所謂的Redis對象頭其實(shí)和Java對象頭很像,都是用來存儲對象信息的,所有的Redis對象都有對象頭,對象頭的數(shù)據(jù)結(jié)構(gòu)如下:
struct RedisObject{
int4 type; //類型,4bits
int4 encoding; //存儲形式,4bits
int24 lru; //lru信息,24bits
int32 refcount; //引用計(jì)數(shù),4bytes
void *ptr; //指針,8bytes
}
所以一個(gè)RedisObject對象頭需要16字節(jié)的存儲空間
embstr和raw的主要區(qū)別就是embstr的內(nèi)存分配是連續(xù)的,而raw則不是連續(xù)的

那為什么以44個(gè)字節(jié)來做分界線呢?我們可以計(jì)算一下,一個(gè)SDS的長度最小是當(dāng)泛型T也為byte類型時(shí),且byte數(shù)組為空時(shí),一共是capacity(1字節(jié)),len(1字節(jié)),flag(1字節(jié)),即一共3字節(jié),而對象頭需要16字節(jié),所以一個(gè)字符串至少需要19個(gè)字節(jié)的內(nèi)存空間
而內(nèi)存分配器分配內(nèi)存都是以2的冪次方進(jìn)行分配,如2/4/8/16/32/64字節(jié),所以內(nèi)存分配器會為字符串至少分配32字節(jié)(16<19<32),此時(shí)會以embstr方式存儲;當(dāng)字符串總體超過了64字節(jié),redis就認(rèn)為它是一個(gè)大字符串,使用raw方式存儲
當(dāng)字符串對象的大小為64字節(jié)時(shí),實(shí)際的字符最大長度為64-19-1=44字節(jié),最后的那個(gè)1字節(jié),是因?yàn)樽址訬ULL結(jié)尾,占用一個(gè)字節(jié)(之所以使用NULL結(jié)尾是為了方便使用glibc的字符串處理函數(shù))
所以當(dāng)字符串實(shí)際長度小于44字節(jié)時(shí),使用embstr存儲;大于44個(gè)字節(jié)時(shí)使用raw方式存儲
最后是String的擴(kuò)容策略,當(dāng)SDS的冗余空間不足以存放字符串時(shí)就需要擴(kuò)容。擴(kuò)容策略是當(dāng)字符串長度小于1MB,擴(kuò)容采取加倍策略,即加倍現(xiàn)有的空間;當(dāng)字符串長度超過1MB時(shí),每次擴(kuò)容只會多分配1MB的空間
注:Redis規(guī)定了字符串的最大長度為512MB
以上內(nèi)容就是關(guān)于String類型在面試中需要特別注意的點(diǎn),小黑板希望這篇文章能夠幫助大家整理好思路,查缺補(bǔ)漏,可以從容不迫的面對面試~
后續(xù)小黑板會繼續(xù)更新數(shù)據(jù)結(jié)構(gòu)系列,幫助大家拆解面試套路哦~

關(guān)注【后端技術(shù)小黑板】,發(fā)送“面試套路”,更多的面試套路拆解和知識分享等你喲~