Redis 底層數據結構
版本:2.9
支持的數據類型:
- 字符串
- 散列
- 列表
- 集合
- 有序集合
字符串
Redis 利用原生的 c 字符串進行了一次封裝。封裝的字符串叫做簡單動態字符串:SDS(simple dynamic string)
Redis 使用的簡單動態字符串比 c 語言原生的字符串有以下優點:
- 獲取字符串長度的復雜度為O(1)
- 不存在緩存區溢出
- 修改字符串長度時,不需要頻繁分配內存
- 空間預分配策略
- 惰性空間策略
- 二進制安全
- 二進制安全的意思是,可以將二進制數據使用 SDS 存儲,而不會存在 c 語言中,遇到 \0 是字符串結尾的情況。
- 兼容部分 c 字符串函數
- 因為 SDS 遵循 c 語言以 \0 結尾的慣例,所以 SDS 可以使用 <string.h> 函數庫,避免了重復代碼
鏈表
鏈表作為最常用的數據結構之一,在 redis 中的使用場景是很多的,其中包括:
- 發布、訂閱
- 列表鍵
- 慢查詢
- 監視器
- 多個客戶端狀態
- 客戶端緩沖區
Redis 中鏈表的幾個特性:
- 雙向鏈表
- 無環
- 有表頭和表尾指針
- 有鏈表長度計數器
- 多態(可以用來保存不同類型的值)
字典
字典又叫符號表,在 PHP 中叫關聯數組,在 JAVA 中叫映射(map),在 Python 中叫字典(dict)。別管這么多叫法,字典就是一種保存鍵值對的一種數據結構。
使用場景
- 散列(hash)
- Redis 數據庫
字典實現
Redis 使用 c 語言構建了自己的字典實現。hash 算法使用的是 murmurhash3 算法。遇到鍵的 hash 值沖突使用的解決方法是鏈地址法。當需要擴展時,Redis 利用兩個哈希表進行漸進式的 rehash。
字典(內部的哈希表)擴展與收縮條件
哈希表內部會通過公式計算一個負載因子。公式為:
load_factor=ht[0].used/ht[0].Size
擴展條件:
- 服務器目前沒有在執行 BGSAVE 命令或者 BGREWRITEAOF 命令,並且哈希表的負載因子大於等於1。
- 服務器目前正在執行 BGSAVE 命令或者 BGREWRITEAOF 命令,並且哈希表的負載因子大於等於5。
收縮條件:負載因子小於 0.1
跳躍表
跳躍表的結構:
跳躍表是一種對標平衡樹的一種數據結構。但是比平衡樹更簡單、更快速、使用更少空間。所以一般都會使用跳躍表。
跳躍表在 Redis 中的使用場景暫時僅限於實現有序集合。
跳躍表的實現參見:http://blog.jobbole.com/111731/
整數集合
整數集合的使用場景為元素不多且只包含整數元素的集合。
使用 c 數組實現。
壓縮列表(ziplist)
壓縮列表是 Redis 為了節省內存實現的。當列表鍵和哈希鍵的項比較少,並且存儲的值比較小時,會使用壓縮列表節省內存。