Redis資料結構

2021-07-09 16:09:04 字數 2160 閱讀 9104

字典(dict)是redis裡最核心的資料結構,正如其全稱remote dictionary service所說,redis其實就是乙個字典服務,字典以key、value的形式呈現給使用者,key是簡單的字串,而value可以是各種資料結構,比如字串(string)、鍊錶(list)、集合(set)、排序集合(zset)、雜湊表(hash)等。

redis裡dict的實現也比較簡單,通過鍊錶來解決雜湊衝突,值得一提的是dict的動態擴充套件能力,當dict裡元素不斷增加時,其會擴大雜湊桶數,然後對現有元素進行rehash,重新分布到對應的桶上,但dict的rehash並不是一次性完成的,這樣會導致當dict裡元素較多時,rehash耗時較長,導致服務阻塞。

typedef struct dict  dict;
dict建立時,會初始化ht[0],插入和訪問都通過ht[0]來完成,當需要rehash時,建立乙個新的dict ht[1],並以桶為單位將ht[0]裡的元素逐步遷移到新的ht[1]上(遷移會在訪問dict時觸發,也可以配置redis主動在後台週期性的遷移)。所以當訪問dict時,如果正在進行rehash,就必須先後查詢ht[0], ht[1],因為被訪問的元素可能已經遷到新的ht[1]上;當所有的元素都遷移到ht[1]後,用ht[1]代替ht[0],並釋放掉原來的ht[0]。

dict是通用的資料結構,採用void*來儲存任意型別的物件,由於需求多變,比如有的場景需要在插入元素時重新分配記憶體,而有的場景直接儲存指標,有的場景需要定製物件比較的方式,redis為解決這個問題,定義了一系列的介面,使用者可以根據需求在建立dict時指定。

typedef struct dicttype  dicttype;
redis所有的key都是string型別,redis的是基於c string的乙個封裝,在字串的頭部儲存了長度資訊(strlen的複雜度為o(1)),並且支援動態擴充套件等特性。

struct sdshdr ;

typedef char *sds;

redis的sds型別其實就是char*,redis建立乙個string時,返回的是buf的指標,通過這個指標,就可以計算出sdshdr的位置,來訪問到len、free等字段。

redis的list實現是乙個雙向鍊錶,與dict類似,list也可以定製物件對比、析構等方法;list在頭結點會儲存鍊錶的長度,使得獲取list長度的複雜度為o(1);頭結點還儲存了list頭部、尾部節點的指標,使得可以從兩個方向遍歷list。

typedef struct listnode  listnode;

typedef struct list list;

雙向鍊錶的的最大問題在於頭尾指標的開銷,64bit os上,每個節點有16bytes的額外開銷,為了節省記憶體,當list裡的元素較少並且大小較小時,redis採用ziplist的格式來實現鍊錶。

ziplist實際上是二進位制的形式組織鍊錶,"二進位制資料"的儲存鍊錶頭部,記錄總長度,頭尾的位置等資訊,然後每個節點除了儲存節點內容外,還記錄自身的長度,以及上乙個節點的長度,這樣通過遍歷"二進位制資料"就能訪問到ziplist裡所有的元素。另外,ziplist節點的長度、以及上乙個節點的長度通過變長整數編碼,進一步節省記憶體。

set代表乙個集合(元素不重複),集合在redis裡實現為字典(字典的value為null);如果set裡所有的元素都是整數時,redis會以intset的形式儲存,intset是乙個排序的整形陣列,為節省記憶體,當intset裡元素值在[int16_min, int16_max]之間時,每個陣列元素佔2個位元組;當inset裡元素值都在[int32_min, int32_max]之間時,每個陣列元素佔4個位元組;否則每個元素佔8個位元組。

zset是排序集合,與set不同的時,zset裡每個元素有乙個score(double型別),作為排序的標準;redis裡zset預設通過乙個dict和乙個ziplist來實現,dict用於維護set元素到score的對映關係,所有的元素都追加到乙個skiplist來保證其排序。當zset裡元素較少並且大小較小時,zset也可以ziplist的形式儲存,zset的元素以及對應的score會作為ziplist的兩個連續節點儲存。

redis的hash是維護filed==>value的對映表,hash的預設實現也是dict,以通過field快速找到value;當hahs裡元素較少並且大小較小時,hash也以ziplist的形式儲存以節省記憶體。

Redis 資料結構

最近接觸到了redis的使用,借這個機會深入的了解一下redis的實現和設計原理。下面先介紹一下redis底層所用到的資料結構。redis的實現幾乎都是基於下面的幾個資料結構之上的。struct sdshdr struct listnode struct list struct dictentry ...

redis 資料結構

今天學習了redis的列表型別 lpush ltrim lrange lpush mylist content ltrim 0,99 lrange 0,1 lrange 兩個引數 分別代表第乙個元素和最後乙個元素 redis的列表型別,可以用來做訊息佇列 使用乙個程序 用lpush命名作為生產者 使...

Redis資料結構

redis有哪些資料結構?基本的是有5種 字串string 列表list 集合set 字典hash 有序集合sortedset。如果是redis中高階使用者,還需要加上下面幾種資料結構hyperloglog geo pub sub以及redis module,像bloomfilter,redisse...