Redis簡單瞭解一

Redis

簡單來說就是,一個鍵值對類型的單線程內存數據庫。

支持String、List、Set、Sorted Set、hashes數據類型。

 

數據結構

簡單動態字符串sds

 

簡單動態字符串(Simple Dynamic String),redis是用C語言寫的,但它的簡單動態字符串卻比C語言的字符串優秀。數據結構如圖:

free:分配了但未使用的內存字節長度
len:已經使用的內存字節長度。不含 '\0'

C語言的字符串結構如圖:

1. 獲取字符串長度複雜的從從 O(N) 變成 O(1)
2. 在操作字符串時可以避免緩衝區溢出
3. 減少了修改字符串引起的內存重分配次數
4. 二進制安全:C語言字符串不能存某些特殊字符串,而簡單動態字符串可以

內存策略:

空間預分配:修改時如果需要擴展,分配空間也分配未使用空間。free = min(len + 1MB)。總長度= len + 1byte + free.
惰性空間釋放:縮短字符串時,不立即釋放空間,而是用free記錄數量

 

鏈表linkedlist

鏈表是一種常用的數據結構,不過C語言沒有內置。實現也簡單。

維護表頭、表尾指針,表長度及操作表的函數。

 

字典與哈希表dict

字典由兩個哈希表組成,其中一個正常情況下是空的,也增加了自己的屬性。

內存策略:擴展與收縮,

漸進式rehash

1. 爲 ht[1] 分配空間
2. 修改 rehashidx 爲0,表示開始 rehash
3. 依次把ht[0] 裏的所有鍵值對 rehash到 ht[1],每rehash 一個,rehashidx 加1
4. 期間 刪除、查找、更新在兩個哈希表上進行,添加元素則在新哈希表上進行。則最後舊錶一定爲空
5. 交互 ht[1] ht[0],同時 把 rehashidx 置爲0

 

跳躍表skiplist

簡單來說,跳躍表是鏈表的一種變形。在鏈表的基礎上添加層level的概念。

待續

 

整數集合intset

從名字可知,用來存儲整數的

contents 數組類型取決於encoding,而encoding取值有:INTSET_ENC_INT16、INTSET_ENC_INT32、INTSET_ENC_INT64,分別代表int16_t、int32_t、int64_t 類型的值。

升級:當新加元素的類型比現有所有元素的類型都長時,先升級整數集合類型,然後添加元素到數組開頭或者末尾。
注意:因爲新元素引起了升級,因此它肯定比所有元素大(爲正數),放末尾;或者比所有元素小(爲負數),放開頭。

使用升級策略目的:提升整數集合的靈活性,再就是節約內存。
另外,整數集合不支持降級。

 

壓縮列表ziplist

壓縮列表是redis爲了節約內存而開發的,由一系列特殊編碼的連續內存塊組成的順序數據結構。包含任何多個節點 entry,每個節點保存一個字節數組或者一個整數值。

注意:跟其他數據結構不同,它不是結構體。嚴格來說它不是數據結構,只是有組織的數據存儲方式而已。

連鎖更新:previous_entry_lenght 記錄了前一個節點長度,用1或則會5個字節。增加或者刪除前一個節點時,當前節點記錄的長度發生變化,因此需要擴展空間。依次需要把後邊連續的內存空間移動。複雜度O(N).
 

redis對象

所謂redis對象,就是一個結構體對象,讓 void *ptr 指向它所使用的上述介紹的各種結構存儲。

 

用它包裝之前說的數據結構構成redis支持的數據類型:

比如ptr指向簡單動態字符串,構成字符串對象:

 

再比如哈希對象:

每種數據類型都有兩種數據結構實現,字符串類型有三種。至於redis底層選擇哪種,自行了解。這裏簡單列舉下數據類型和結構組合

對象

對應type

可用編碼

 

字符串

REDIS_STRING

REDIS_ENCODING_INT 

利用整數值實現的字符串

REDIS_ENCODING_EMBSTR

利用embstr編碼的sds實現的字符串對象

REDIS_ENCODING_RAW 

利用簡單動態字符串實現的字符串

列表

REDIS_LIST

REDIS_ENCODING_ZIPLIST 

使用壓縮列表實現列表對象

REDIS_ENCODING_LINKEDLIST

使用雙端列表實現列表對象

哈希對象

REDIS_HASH 

REDIS_ENCODING_ZIPLIST 

使用壓縮列表實現哈希對象

REDIS_ENCODING_HT

使用字典實現哈希對象

集合

REDIS_SET

REDIS_ENCODING_INSET

使用整數集合實現集合對象

REDIS_ENCODING_HT

使用字典實現集合對象

有序集合

REDIS_ZSET 

REDIS_ENCODING_ZIPLIS

使用壓縮列表實現有序集合對象

REDIS_ENCODING_SKIPLIST

使用跳躍表和字典實現有序集合對象

 

 

數據庫

redis 服務器就是一個內存數據庫。所有數據都保存在redisServer 結構中,其中又分鍵空間與過期空間兩個字典:

服務器上可以有多個數據庫,一般我們操作的是db[0],如果需要切換數據庫,執行 SELECT x; x是數據庫序號

對於每個數據庫,都有鍵空間與過期空間。顧名思義

鍵空間存儲鍵值對。

過期空間存儲過期時間數據,但兩個空間是共用鍵的。

 

客戶端

所有客戶端都存在list *clients 中,是一個列表。

 

 

 

 

 

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