redis有5種對(duì)外公開的數(shù)據(jù)結(jié)構(gòu)蜜宪,它們分別是string(字符串)豹储、hash(哈希)桃漾、list(列表)坏匪、set(集合)、zset(有序集合)撬统,實(shí)際上每種數(shù)據(jù)結(jié)構(gòu)都有多種內(nèi)部編碼實(shí)現(xiàn)适滓,這樣redis就會(huì)在合適的場(chǎng)景選擇合適的內(nèi)部編碼。
可以用type key
命令查詢數(shù)據(jù)結(jié)構(gòu)恋追,用object encoding key
命令查詢內(nèi)部編碼凭迹。
redis這樣設(shè)計(jì)有兩個(gè)好處:
- ,可以改進(jìn)內(nèi)部編碼苦囱,而對(duì)外的數(shù)據(jù)結(jié)構(gòu)和命令沒有影響蕊苗,這樣一旦開發(fā)出更優(yōu)秀的內(nèi)部編碼,無需改動(dòng)外部數(shù)據(jù)結(jié)構(gòu)和命令沿彭,符合開閉原則
- 多種內(nèi)部編碼實(shí)現(xiàn)可以在不同場(chǎng)景下發(fā)揮各自的優(yōu)勢(shì)
string
string是redis最基礎(chǔ)朽砰、最常用的數(shù)據(jù)結(jié)構(gòu),首先所有key都是string類型喉刘,而且其他幾種數(shù)據(jù)結(jié)構(gòu)都是在字符串類型基礎(chǔ)上構(gòu)建的瞧柔,字符串類型的值實(shí)際可以是字符串(簡(jiǎn)單的字符串、復(fù)雜的字符串(例如JSON睦裳、XML))造锅、數(shù)字(整數(shù)、浮點(diǎn)數(shù))廉邑,甚至是二進(jìn)制(圖片哥蔚、音頻、視頻)蛛蒙,但是值最大不能超過512MB
內(nèi)部編碼
字符串類型的內(nèi)部編碼有3種:
- int:8個(gè)字節(jié)的長(zhǎng)整型
- embstr:小于等于39個(gè)字節(jié)的字符串
- raw:大于39個(gè)字節(jié)的字符串
應(yīng)用場(chǎng)景
string是redis最基本的數(shù)據(jù)結(jié)構(gòu)糙箍,除了提供最基礎(chǔ)的應(yīng)用場(chǎng)景——緩存之外,還可以利用string的內(nèi)部編碼int進(jìn)行計(jì)數(shù)牵祟,例如記錄文章的點(diǎn)贊數(shù)閱讀量等深夯。
優(yōu)化
hash
在Redis中,哈希類型是指鍵值本身又是一個(gè)鍵值對(duì)結(jié)構(gòu),形如key={{field1咕晋,value1}雹拄,...{fieldN,valueN}}
內(nèi)部編碼
ziplist(壓縮列表):當(dāng)哈希類型元素個(gè)數(shù)小于hash-max-ziplist-entries配置(默認(rèn)512個(gè))掌呜、同時(shí)所有值都小于hash-max-ziplist-value配置(默認(rèn)64字節(jié))時(shí)滓玖,Redis會(huì)使用ziplist作為哈希的內(nèi)部實(shí)現(xiàn),ziplist使用更加緊湊的結(jié)構(gòu)實(shí)現(xiàn)多個(gè)元素的連續(xù)存儲(chǔ)质蕉,所以在節(jié)省內(nèi)存方面比hashtable更加優(yōu)秀呢撞。
hashtable(哈希表):當(dāng)哈希類型無法滿足ziplist的條件時(shí),Redis會(huì)使用hashtable作為哈希的內(nèi)部實(shí)現(xiàn)饰剥,因?yàn)榇藭r(shí)ziplist的讀寫效率會(huì)下降,而hashtable的讀寫時(shí)間復(fù)雜度為O(1)摧阅。
應(yīng)用場(chǎng)景
相比于使用字符串序列化緩存信息汰蓉,哈希類型變得更加直觀,并且在更新操作上會(huì)更加便捷棒卷。所以一般需要頻繁部分更新的緩存信息采用hash數(shù)據(jù)結(jié)構(gòu)顾孽。
優(yōu)化
list
列表(list)類型是用來存儲(chǔ)多個(gè)有序的字符串,比规,列表中的每個(gè)字符串稱為元素(element)若厚,一個(gè)列表最多可以存儲(chǔ)個(gè)元素。在Redis中蜒什,可以對(duì)列表兩端插入(push)和彈出(pop)测秸,還可以獲取指定范圍的元素列表、獲取指定索引下標(biāo)的元素等灾常。列表是一種比較靈活的數(shù)據(jù)結(jié)構(gòu)霎冯,可以充當(dāng)棧和隊(duì)列的角色。
列表類型有兩個(gè)特點(diǎn):
- 列表中的元素是有序的沈撞,這就意味著可以通過索引下標(biāo)獲取某個(gè)元素或者某個(gè)范圍內(nèi)的元素列表。
- 列表中的元素可以是重復(fù)的雕什。
內(nèi)部編碼
- ziplist(壓縮列表):當(dāng)列表的元素個(gè)數(shù)小于list-max-ziplist-entries配置(默認(rèn)512個(gè))缠俺,同時(shí)列表中每個(gè)元素的值都小于list-max-ziplist-value配置時(shí)(默認(rèn)64字節(jié)),Redis會(huì)選用ziplist來作為列表的內(nèi)部實(shí)現(xiàn)來減少內(nèi)存的使用贷岸。
- linkedlist(鏈表):當(dāng)列表類型無法滿足ziplist的條件時(shí)壹士,Redis會(huì)使用linkedlist作為列表的內(nèi)部實(shí)現(xiàn)。
應(yīng)用場(chǎng)景
- 消息隊(duì)列
Redis的lpush+brpop命令組合即可實(shí)現(xiàn)阻塞隊(duì)列偿警,生產(chǎn)者客戶端使用lrpush從列表左側(cè)插入元素墓卦,多個(gè)消費(fèi)者客戶端使用brpop命令阻塞式的“搶”列表尾部的元素,多個(gè)客戶端保證了消費(fèi)的負(fù)載均衡和高可用性户敬。
set
集合(set)類型也是用來保存多個(gè)的字符串元素落剪,但和列表類型不一樣的是睁本,集合中不允許有重復(fù)元素,并且集合中的元素是無序的忠怖,不能通過索引下標(biāo)獲取元素呢堰。,一個(gè)集合最多可以存儲(chǔ)個(gè)元素凡泣。Redis除了支持集合內(nèi)的增刪改查枉疼,同時(shí)還支持多個(gè)集合取交集、并集鞋拟、差集
內(nèi)部編碼
- intset(整數(shù)集合):當(dāng)集合中的元素都是整數(shù)且元素個(gè)數(shù)小于set-max-intset-entries配置(默認(rèn)512個(gè))時(shí)骂维,Redis會(huì)選用intset來作為集合的內(nèi)部實(shí)現(xiàn),從而減少內(nèi)存的使用贺纲。
- hashtable(哈希表):當(dāng)集合類型無法滿足intset的條件時(shí)航闺,Redis會(huì)使用hashtable作為集合的內(nèi)部實(shí)現(xiàn)。
應(yīng)用場(chǎng)景
集合類型比較典型的使用場(chǎng)景是標(biāo)簽(tag)猴誊。例如一個(gè)用戶可能對(duì)娛樂潦刃、體育比較感興趣,另一個(gè)用戶可能對(duì)歷史懈叹、新聞比較感興趣乖杠,這些興趣點(diǎn)就是標(biāo)簽。有了這些數(shù)據(jù)就可以得到喜歡同一個(gè)標(biāo)簽的人澄成,以及用戶的共同喜好的標(biāo)簽胧洒,這些數(shù)據(jù)對(duì)于用戶體驗(yàn)以及增強(qiáng)用戶黏度比較重要。例如一個(gè)電子商務(wù)的網(wǎng)站會(huì)對(duì)不同標(biāo)簽的用戶做不同類型的推薦墨状,比如對(duì)數(shù)碼產(chǎn)品比較感興趣的人略荡,在各個(gè)頁面或者通過郵件的形式給他們推薦最新的數(shù)碼產(chǎn)品,通常會(huì)為網(wǎng)站帶來更多的利益歉胶。
優(yōu)化
zset
有序集合它保留了集合不能有重復(fù)成員的特性汛兜,但不同的是,有序集合中的元素可以排序通今。但是它和list列表使用索引下標(biāo)作為排序依據(jù)不同的是粥谬,它給每個(gè)元素設(shè)置一個(gè)分?jǐn)?shù)(score)作為排序的依據(jù)。有序集合提供了獲取指定分?jǐn)?shù)和元素范圍查詢辫塌、計(jì)算成員排名等功能漏策,合理的利用有序集合,能幫助我們?cè)趯?shí)際開發(fā)中解決很多問題臼氨。
內(nèi)部編碼
- ziplist(壓縮列表):當(dāng)有序集合的元素個(gè)數(shù)小于zset-max-ziplist-entries配置(默認(rèn)128個(gè))掺喻,同時(shí)每個(gè)元素的值都小于zset-max-ziplist-value配置(默認(rèn)64字節(jié))時(shí),Redis會(huì)用ziplist來作為有序集合的內(nèi)部實(shí)現(xiàn),ziplist可以有效減少內(nèi)存的使用感耙。
- skiplist(跳躍表):當(dāng)ziplist條件不滿足時(shí)褂乍,有序集合會(huì)使用skiplist作為內(nèi)部實(shí)現(xiàn),因?yàn)榇藭r(shí)ziplist的讀寫效率會(huì)下降即硼。
應(yīng)用場(chǎng)景
有序集合比較典型的使用場(chǎng)景就是排行榜系統(tǒng)逃片。例如視頻網(wǎng)站需要對(duì)用戶上傳的視頻做排行榜,榜單的維度可能是多個(gè)方面的:按照時(shí)間只酥、按照播放數(shù)量褥实、按照獲得的贊數(shù)。
參考文獻(xiàn):
《Redis開發(fā)與運(yùn)維》——付磊