成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

了解 Redis 列表基本原理,一文足矣!

存儲 存儲軟件 Redis
上次我們分享 Redis 字符串的底層原理,今天我們再來看下 Redis List 列表的底層原理。

[[360732]]

 本文轉載自微信公眾號「Java極客技術」,作者鴨血粉絲 。轉載本文請聯系Java極客技術公眾號。   

Hello,大家好,我是阿粉~

上次我們分享 Redis 字符串的底層原理,今天我們再來看下 Redis List 列表的底層原理。

Redis List 命令

Redis List 列表支持的相關指令比較多,比如單個元素增加、刪除操作,也支持多個元素范圍操作。

Redis List 列表支持列表表頭元素插入/彈出(「LPUSH/LPOP」),也支持表尾元素插入/彈出(「RPUSH/RPOP」)。

另外 Redis List 列表還支持根據下標(「LINDEX」 )獲取元素,也支持根據根據下標覆蓋相應的元素(「LSET」 )。

除此之外,Redis List 列表還支持的范圍操作,比如獲取指定范圍內全部元素(「LRANGE」 ),移除指定范圍內的全部元素(「LTRIM」 )。

了解完的 Redis 相關指令,我們來看下 Redis List 列表底層實現方式,使用兩種數據結構:

  • 壓縮列表(ziplist)
  • 雙向列表(linkedlist)

 

ps:本篇文章基于 Redis 3.2 開始進行講解

雙向列表(linkedlist)

上面我們知道了List 列表支持表頭/表尾元素的插入/彈出,這類操作使用鏈表那就非常高效,時間復雜度為 O(1)。

Redis 雙向列表(linkedlist) 由兩個結構構成:

  • list
  • listnode

結構如下:

 

list 結構體中保存了表頭節點,表尾節點以及鏈表包含的節點的數量,正因為如此操作表頭/表尾元素的插入/彈出,鏈表長度的計算將會非常高效,時間復雜度為「O(1)」。

listnode結構體中除了保存節點的值以外,還會保存前后節點的指針,這樣如果需要獲取某個節點的前置節點與后置節點也會非常高效,時間復雜度為「O(1)」。

另外如果需要指定位置插入/刪除元素,那么只需要變動當前位置節點前后指針即可,這個插入/刪除操作復雜度為「O(1)」。

不過需要注意了,插入/刪除動作前提我們需要找到這個指定位置,這個查找動作我們只能遍歷鏈表,復雜度為「O(N)」,所以插入/刪除的復雜度為「O(N)」。

雙向列表(linkedlist)除了用作在列表鍵以外,還廣泛用于發布/訂閱,慢查詢等內部操作。

既然雙向列表(linkedlist)可以滿足列表鍵的操作,那為什么 Redis 列表還采用其他的數據結構?

其實主要是因為內存占用問題,雙向鏈表由于使用兩個結構體,而這兩個結構體都需要保存一些必要信息,這必然將會占用部分內存。

而當元素很少的時候,如果直接使用雙向鏈表,內存還是比較浪費的。所以 Redis 引入壓縮列表。

壓縮列表

壓縮列表是 Redis 為了節約內存而開發,它由一系列的特殊編碼的的「連續內存塊」組成的順序型數據結構,整體結構如下:

 

從上面結構可以看出來,壓縮列表實際上類似與我們使用的數組,數組中每一個元素保存一個數據。

不過與數組不同的是,壓縮列表的表頭存在三個字段

  • zlbytes 代表列表長度
  • zltail代表列表尾節點距離壓縮列表起始地址的偏移量
  • zllen代表壓縮列表的節點的個數

另外壓縮列表的表尾還有一個字段,zlend里面保存一個特殊的值, OXFE,用于標記壓縮列表的末端。

一個壓縮列表可以由多個節點構成,每個節點可以保存整數值或字節數組,結構如下:

 

使用壓縮列表,如果查找定位表頭元素,我們只需要使用壓縮列表起始地址加上表頭三個字段長度就可以直接點位,查找非???,復雜度是 O(1)。

而壓縮列表的最后一個元素,查找起來也非常輕松,我們使用壓縮列表起始地址加上zltail包含的長度就可以直接點位,查找也非??欤瑥碗s度是 O(1)。

至于列表中的其他元素,就沒有這么好運了,我們只能從第一個元素或者最后一個元素,遍歷列表查找,此時的復雜度就是 O(N) 了。

另外壓縮列表的新增、刪除元素,都將會導致重新分配內存,效率不高,平均復雜度為 O(N),最壞福復雜度為 O(N^2)。

編碼轉換

當我們創建一個 Redis 列表鍵,如果同時滿足以下兩個條件,列表對象將會使用壓縮列表作為底層數據結構

列表對象保存的所有字符串元素的長度都小于 64 字節

列表對象中保存的元素數量小于 512 個

如果不能同時滿足這兩個條件,那么默認將會使用雙向列表作為底層數據結構。

小結

Redis 列表底層使用兩種數據結構,壓縮列表與雙向鏈表。

壓縮列表由于使用了連續內存塊,內存占用少,并且內存利用率高,但是新增、刪除由于涉及重新分配內存,效率不高。

雙向列表呢,新增、刪除元素非常方便,但是由于每個節點都是獨立的內存快,內存占用比較高,且內存碎片化嚴重。

這兩種數據結構在表頭/表尾插入與刪除元素,都十分高效。但是其他操作,可能就效率較低。

所以我們使用 Redis 列表,一定要因地制宜,可以將其當做 FIFO 隊列,這樣僅使用 POP/PUSH ,效率將會很高。

 

參考資料

Redis 設計與實現

 

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2021-04-27 19:21:48

HBase原理開源

2023-04-26 13:48:36

2012-01-12 14:37:34

jQuery

2016-08-17 23:53:29

網絡爬蟲抓取系統

2020-05-20 22:28:10

JVM運行機制

2009-02-24 09:43:00

IP電話原理

2011-11-29 12:17:00

2017-09-11 17:16:35

2020-08-20 07:41:52

Git原理版本

2019-11-28 10:45:28

ZooKeeper源碼分布式

2016-08-18 00:04:09

網絡爬蟲抓取系統服務器

2010-08-20 13:29:33

OFDM

2020-03-21 14:57:14

手機定位智能手機APP

2013-04-07 14:09:55

Android應用基本

2024-01-03 08:59:52

2021-02-08 21:40:04

SockmapBPF存儲

2011-07-07 14:10:21

Cocoa 內省 hash

2009-06-11 09:56:09

MySQL Repli原理

2020-12-29 16:55:44

ZooKeeper運維數據結構

2010-03-17 13:35:02

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一级a性色生活片久久毛片 午夜精品在线观看 | 久久影院一区 | 成人九区| 久草新在线 | 精品成人免费视频 | 日韩一区二区三区在线视频 | 丁香综合| 欧美成年网站 | 九九热精品视频 | 欧美综合一区二区 | 97精品视频在线 | 一区二区高清不卡 | 欧美黑人一区 | 中文视频在线 | 国产精品毛片一区二区三区 | 欧美激情网站 | 国产成人综合在线 | 日本午夜网 | 亚洲在线一区二区 | 999热精品视频 | 久久大陆 | 久久精品免费观看 | av色在线| av天天操| 久久99精品国产麻豆婷婷 | 欧美日韩久久精品 | 国产精品久久久久久妇女6080 | 久久久黄色 | 日日天天 | 久久久久九九九女人毛片 | 日韩欧美国产综合 | 久久久国产精品视频 | 日韩成人在线播放 | 欧美日韩专区 | 午夜成人免费视频 | 亚洲免费久久久 | 国产区精品 | 操久久| 国产一二区视频 | 久久专区 | www久久爱|