重溫算法Day26:Redis常用的數據結構

Redis 主要是作爲內存數據庫來使用,也就是說,數據是存儲在內存中的。儘管它經常被用作內存數據庫,但是,它也支持將數據存儲在硬盤中。

Redis 中,鍵的數據類型是字符串,但是爲了豐富數據存儲的方式,方便開發者使用,值的數據類型有很多,常用的數據類型有這樣幾種,它們分別是字符串、列表、字典、集合、有序集合。

壓縮列表:是 Redis 自己設計的一種數據存儲結構。它有點兒類似數組,通過一片連續的內存空間,來存儲數據。不過,它跟數組不同的一點是,它允許存儲的數據大小不同。
壓縮列表這種存儲結構,一方面比較節省內存,另一方面可以支持不同類型數據的存儲。而且,因爲數據存儲在一片連續的內存空間,通過鍵來獲取值爲列表類型的數據,讀取的效率也非常高。
壓縮列表不支持隨機訪問,有點類似鏈表。Redis一般都是通過key獲取整個value的值,也就是整個壓縮列表的數據,並不需要隨機訪問。

當列表中存儲的數據量比較大的時候,也就是不能同時滿足剛剛講的兩個條件的時候,列表就要通過雙向循環鏈表來實現了。
Redis 的這種雙向鏈表的實現方式,非常值得借鑑。它額外定義一個 list 結構體,來組織鏈表的首、尾指針,還有長度等信息

// 以下是C語言代碼,因爲Redis是用C語言實現的。
typedef struct listnode {
  struct listNode *prev;
  struct listNode *next;
  void *value;
} listNode;


typedef struct list {
  listNode *head;
  listNode *tail;
  unsigned long len;
  // ....省略其他定義
} list;

字典(hash)
只有當存儲的數據量比較小的情況下,Redis 才使用壓縮列表實現字典。
(1)字典中保存的鍵和值的大小都要小於 64 字節;
(2)字典中鍵值對的個數要小於 512 個。

當不能同時滿足上面兩個條件的時候,Redis 就使用散列表來實現。
Redis 使用MurmurHash2這種運行速度快、隨機性好的哈希算法作爲哈希函數。對於哈希衝突問題,Redis 使用鏈表法來解決。除此之外,Redis 還支持散列表的動態擴容、縮容(分批次)。

集合(set)
用來存儲一組不重複的數據。
基於有序數組:存儲的數據都是整數;存儲的數據元素個數不超過 512 個。
基於散列表。
有序集合(sortedset)
用來存儲一組數據,並且每個數據會附帶一個得分。通過得分的大小,我們將數據組織成跳錶這樣的數據結構,以支持快速地按照得分值、得分區間獲取數據。
當數據量比較小的時候,Redis 會用壓縮列表來實現有序集合。所有數據的大小都要小於 64 字節;元素個數要小於 128 個。

數據結構持久化
第一種是清除原有的存儲結構,只將數據存儲到磁盤中。當我們需要從磁盤還原數據到內存的時候,再重新將數據組織成原來的數據結構。(Redis採用)
弊端:數據從硬盤還原到內存的過程,會耗用比較多的時間。比如,我們現在要將散列表中的數據存儲到磁盤。當我們從磁盤中,取出數據重新構建散列表的時候,需要重新計算每個數據的哈希值。

第二種方式是保留原來的存儲格式,將數據按照原有的格式存儲在磁盤中。我們可以將散列表的大小、每個數據被散列到的槽的編號等信息,都保存在磁盤中。有了這些信息,我們從磁盤中將數據還原到內存中的時候,就可以避免重新計算哈希值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章