新聞中心
【稿件】面試官:Redis 有哪幾種數(shù)據(jù)類型?存儲(chǔ)原理是什么?具體適應(yīng)哪些應(yīng)用場(chǎng)景?是否歷歷在目,這是 Redis 關(guān)于數(shù)據(jù)類型的面試 3 連問,是除“Redis 持續(xù)化”外的最常見 Redis 考題。

[[387092]]
圖片來自 Pexels
但是,無論面試官的提問、網(wǎng)上的答案,基本都是錯(cuò)的!本文將依據(jù)源碼向讀者做剖析,深入淺出,過目不忘。
查谷歌眾說紛紜
說法一:5 種
Redis 支持 5 種數(shù)據(jù)類型:
- String(字符串)
- List(列表)
- Set(集合)
- Sorted Set(有序集合)
- Hash(哈希)
這也是被行業(yè)普遍認(rèn)可,最最常見的答案。至于這 5 種類型的詳解,網(wǎng)上已經(jīng)鋪天蓋地,這里不打算重復(fù)探討,請(qǐng)讀者自行溫習(xí)。
說法二:6 種
包含了“說法一”的 5 種,還包含了:HyperLogLog(基數(shù))。
也就是:String(字符串)、List(列表)、Set(集合)、Sorted Set(有序集合)、Hash(哈希)、HyperLogLog(基數(shù))共 6 種。
說法三:9 種
包含了“說法二”的 6 種,還包含了:Bitmap(位集合)、Geospatial(地理空間索引)、Streams(流信息)3 種。
也就是:String(字符串)、List(列表)、Set(集合)、Sorted Set(有序集合)、Hash(哈希)、HyperLogLog(基數(shù))、Bitmap(位集合)、Geospatial(地理空間索引)、Streams(流信息)共 9 種。
還有一說,并未包含 Streams(流信息),但是包含了 BloomFilter(布隆過濾器),這個(gè)不重要,但都稱是 9 種,尚未見有 10 種的說法。
從官網(wǎng)找答案
英文官網(wǎng):https://redis.io/,中文官網(wǎng):http://www.redis.cn/,首頁(yè)如下:
請(qǐng)留意這一句:
Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams.
很明顯,官網(wǎng)提到 Redis 支持的數(shù)據(jù)類型一共有 9 種。跟上文的“說法三”基本一致。
另外值得注意的是,中文官網(wǎng)沒有提及 Stream,也就是漏了一句話。因?yàn)?Stream 是在 2018 年 10 月 5.0 版本引入,但是中文官網(wǎng)至今沒有更新,是個(gè)非常明顯的文案 Bug(不知道反饋被采納會(huì)不會(huì)有獎(jiǎng)金)。
那么問題到此解決了?還沒有!問題才剛剛開始。
具體問題具體分析
“說法一:5 種” 為什么會(huì)被行業(yè)普遍認(rèn)可
先來看看 Redis 的各種高級(jí)功能類型被引入的版本,如下表:
很明顯,原因是:這些功能都是后續(xù)版本陸續(xù)引入的,5 種數(shù)據(jù)類型乃最經(jīng)典的 5 種類型,所以代代相傳,傳承已久。
再來看看 Redis 的各個(gè)大版本的發(fā)布時(shí)間,如下表:
也就是說,“5 種數(shù)據(jù)類型”的認(rèn)知,業(yè)界持續(xù)已有 10 年之久,認(rèn)知的錯(cuò)誤也有 10 年之久。
“說法三:9 種” 是否正確
要回答這個(gè)問題,先了解 Redis 的數(shù)據(jù)類型如何查看,可通過 type KEY_NAME 命令。
另外,通過 object encoding KEY_NAME 命令可查具體的編碼結(jié)構(gòu),這里僅稍作提及,不在本文的討論范圍內(nèi)。
①String
- localhost:6379> set str:hello world
- OK
- localhost:6379> get str:hello
- "world"
- localhost:6379> type str:hello
- string
②Bitmap
- localhost:6379> setbit str:a 1 1
- (integer) 0
- localhost:6379> setbit str:a 2 1
- (integer) 0
- localhost:6379> setbit str:a 7 1
- (integer) 0
- localhost:6379> get str:a
- "a"
- localhost:6379> type str:a
- string
很明顯,Bitmap 底層也是 String 實(shí)現(xiàn),賦值的每一個(gè) bit 均對(duì)應(yīng) ASCII 碼的二進(jìn)制位。
③HyperLogLog
- 127.0.0.1:6379> PFADD hyperLogLog:db "redis"
- (integer) 1
- 127.0.0.1:6379> PFADD hyperLogLog:db "mongodb"
- (integer) 1
- 127.0.0.1:6379> PFADD hyperLogLog:db "mysql"
- (integer) 1
- 127.0.0.1:6379> PFCOUNT hyperLogLog:db
- (integer) 3
- 127.0.0.1:6379> get hyperLogLog:db
- "HYLL\x01\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00H\x91\x80\\g\x84[\x03"
- 127.0.0.1:6379> type hyperLogLog:db
- string
很明顯,HyperLogLog 底層也是 String 實(shí)現(xiàn),與其說 HyperLogLog 是一種單獨(dú)的數(shù)據(jù)類型,倒不如說是對(duì) String 數(shù)據(jù)類型做 API 封裝的應(yīng)用程序。
④歸納
其他幾種高級(jí)功能類型的驗(yàn)證方式同,這里不做贅述,留給讀者自行驗(yàn)證。
這里歸納結(jié)論如下:
饒了一圈似乎又回到了起點(diǎn),“說法一:5 種”其實(shí)并沒有錯(cuò)?畢竟任何類型的底層都是基于 5 種之一實(shí)現(xiàn)的。接著往下說。
Talk is cheap, Show me the code.
能說算不上什么,有本事就把你的代碼給我看看。
源碼文件列表
如下圖:
t_(type) 開頭的,有且僅有 6 個(gè),除了“5 種數(shù)據(jù)類型”外,還包含了:t_stream。
Stream 是 Redis 5.0 版本引入的一個(gè)新的數(shù)據(jù)類型,支持消費(fèi)者組,借鑒 Kafka 設(shè)計(jì)的支持多播的可持久化消息隊(duì)列(支持 group,不支持 partition)。
我們做下驗(yàn)證:
- localhost:6379[2]> XADD stream:info * name aku alias bumblebee age 35 address sz
- "1615012000623-0"
- localhost:6379[2]> type stream:info
- stream
沒有問題:6 種,讓我們重新梳理一下:
- String(字符串)
- List(列表)
- Set(集合)
- Sorted Set(有序集合)
- Hash(哈希)
- Streams(流信息)
源碼就是源碼,讓人豁然開朗,查谷歌眾說紛紜、千篇一律,確實(shí)都不對(duì)!
那么問題答案到此解決?還沒有。但現(xiàn)在已經(jīng)不是剛剛開始了,只差最后一步。
源碼內(nèi)容
不能徒有其表,只看源碼文件列表,不看源碼內(nèi)容。
這是關(guān)于類型的枚舉定義,0 到 6,什么?OBJ_MODULE?這是什么鬼?
請(qǐng)留意這一句描述:
* The "module" object type is a special one that signals that the object
* is one directly managed by a Redis module.
尤其是 special 一詞,這是 special 的類型,其余 6 類都是非 special 類型。既然 special,為什么其枚舉值是 5 會(huì)夾在 hash 和 stream 的非 special 之間?
歷史原因,Redis 4.0 引入了模塊擴(kuò)展功能,當(dāng)時(shí)已經(jīng)認(rèn)為是最后一個(gè)類型。
但是 Redis 5.0 又引入了 Stream 數(shù)據(jù)結(jié)構(gòu),可能是覬覦 Kafka 的市場(chǎng)份額,說白跟 RocketMQ 一樣都是仿照 Kafka 去實(shí)現(xiàn)的。
言歸正傳,所以該枚舉值的定義是不是跟我們?nèi)粘I(yè)務(wù)開發(fā)的場(chǎng)景似曾相識(shí),因?yàn)闋顟B(tài)值編號(hào)已經(jīng)被占了,那么新加的狀態(tài)值就只能往后面排,導(dǎo)致五花八門一點(diǎn)都不連續(xù)。沒錯(cuò),就這么接地氣。
那么,module 用在什么場(chǎng)景?有很多場(chǎng)景,舉個(gè)最常用的例子:Leaky Bucket(漏桶算法),也就是 Redis 4.0 引入的 redis-cell 模塊。
示例如下:
- > cl.throttle module:leaky 14 30 60 1
- 1) (integer) 0 # 0 表示允許 1 表示拒絕
- 2) (integer) 15 # 漏斗容量 capacity
- 3) (integer) 14 # 漏斗剩余空間 left_quota
- 4) (integer) -1 # 如果拒絕了,需要多長(zhǎng)時(shí)間后再重試,單位秒
- 5) (integer) 2 # 多長(zhǎng)時(shí)間后,漏斗完全空出來,單位秒
那么問題答案到此解決?是的,通過分析源碼終于有了結(jié)論。
結(jié)論
Q:Redis 有哪幾種數(shù)據(jù)類型?
A:Redis 6.0 最新版本有且僅有 7 種。
按源碼中枚舉值定義的順序,分別為:
- String(字符串)
- List(列表)
- Set(集合)
- Sorted Set(有序集合)
- Hash(哈希)
- Module(模塊)
- Streams(流信息)
Q:高級(jí)功能類型,比如 HyperLogLog、Bitmap 等呢?
A:高級(jí)功能類型是對(duì)數(shù)據(jù)類型做 API 封裝的應(yīng)用程序。
HyperLogLog、Bitmap、Bloom Filter 的底層都是 String 數(shù)據(jù)類型,Geospatial 的底層是 Sorted Set 數(shù)據(jù)類型,cl.throttle(Redis-Cell) 的底層是 Module 數(shù)據(jù)類型。均可通過 type KEY_NAME 命令逐一核對(duì)。
所以,當(dāng)面試官下次問你“Redis 數(shù)據(jù)類型的面試 3 連問”時(shí)候,可以好好的懟回去了,讓面試官看到你的理解、你對(duì)底層邏輯的掌握比面試官本人更系統(tǒng)、更專業(yè),給面試官帶來些許的驚喜,相信面試效果會(huì)完全不一樣。
萬一驚喜變成了驚嚇怎么辦?也許該團(tuán)隊(duì)是個(gè)固執(zhí)己見的守舊團(tuán)隊(duì),面試官的考題可能也只是來自照本宣科的題庫(kù),那么你可以把你的簡(jiǎn)歷慢慢合上,揮一揮衣袖不帶走一片云彩。
最后,Talk is cheap,Show me the code。實(shí)踐才是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),共勉,請(qǐng)不要再錯(cuò)下去了。
作者:大黃蜂
簡(jiǎn)介:曾就職于華為、騰訊等大型互聯(lián)網(wǎng)公司,于 2018 年 5 月加盟獨(dú)角獸公司 akulaku 擔(dān)任技術(shù)管理職務(wù),對(duì)分期、金融借貸等核心系統(tǒng)的架構(gòu)設(shè)計(jì)具有豐富的實(shí)戰(zhàn)經(jīng)驗(yàn)。精通 Redis 和 JVM,非常重視底層原理,對(duì)高級(jí)用法、協(xié)議、源碼等具有深入的研究。并且,具有自己獨(dú)特的團(tuán)隊(duì)管理理念,另辟蹊徑,專注研發(fā)質(zhì)量和效率,為公司培養(yǎng)出多名青年高潛,并多次榮獲各類表彰。
編輯:陶家龍
征稿:有投稿、尋求報(bào)道意向技術(shù)人請(qǐng)?zhí)砑有【幬⑿?gordonlonglong
【原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為.com】
文章標(biāo)題:今天我才知道Redis有7種數(shù)據(jù)類型...
文章來源:http://www.dlmjj.cn/article/cdhhigs.html


咨詢
建站咨詢
