Redis中的基本資料結構

2022-09-20 02:12:16 字數 3210 閱讀 7718

資料結構

typedef struct sdstr
sds是字串物件的底層實現之一

sds的特性

賦值操作會統計字串的長度然後將字串存入buff裡面,同時設定長度和使用的長度

例如 "hello"這個字串的儲存結構如下

修改的時候會比較麻煩,分為兩種情況

一是由段字串變長:例如:由"hello"變為"hello,redis".

這個時候系統會檢查原本的sds字串是否有空餘空間,剩餘空間為0,會分配等同於修改後字串長度的剩餘空間給sds,這個時候字串的free屬性會變為11,然後執行sdscat(),這個時候buff會變為['h','e','l','l','o',',','r','e','d','i','s','\0'],然後將字串長度len修改為11

最終結構如下

ps:當長度小於1m是翻倍擴容,超過1m時是以1m為標準定量擴容

二是由長字串變短

例如:由"hello,redis"變為"redis",這個時候會釋放多餘空間,同時把free值設為多出來的空間,以便下次使用方便

修改後的結構大概如下

需要釋放的時候可以手動呼叫函式來釋放空間

為什麼要使用sds?

sds可以杜絕緩衝區溢位的問題,獲取字串長度複雜度為常數

二進位制安全,sds使用len屬性來判斷字串的結束

減少字串修改時的記憶體重分配次數

資料結構

//鍊錶節點

typedef struct listnodelistnode;

//鍊錶

typedef struct list

鍊錶是列表物件的底層實現之一

鍊錶在redis中主要負責的是儲存和維護某一類物件,所常用到的操主要有遍歷,修改等

鍊錶在redis中使用極為廣泛,redis的事務,發布與訂閱,伺服器中維護的redisclient資訊等都是用鍊錶結構進行的儲存

資料結構

//雜湊表

typedef struct dictht dictht;

//雜湊節點

typedef struct dictentry v;

struct dictentry *next;

}dictentry;

//字典

typedef struct dictdict;

字典是資料庫的底層實現

解決鍵衝突

redis使用鏈位址法(separate chaining)來解決鍵衝突,當兩個鍵的index值相同時,會把第二個鍵放到第乙個鍵的前面,查詢時對這個index的雜湊節點鍊錶進行遍歷

rehash:

當雜湊表的負載因子(load factor)大於設定值時(平時為1,在bgrewriteaof時為5),雜湊表會進行rehash操作

rehash採用漸進式的方式進行執行,具體流程就是把ht[0]裡面的資料重新進行雜湊計算放到ht[1],此時的雜湊查詢操作兩個表同時提供服務,寫入操作則只有ht[1]提供,這樣ht[0]處於只減不增的狀態,最終當ht[0]裡面的所有資料都被轉移到ht[1]時,rehashidx被設為-1,表明rehash結束,刪除ht[0],並將ht[1]設為ht[0],同時重新分配新的ht[1]

ps:負載因子 = used /size;

資料結構

//跳躍表節點

typedef struct zskiplistnode level;

} zskiplistnode;

//跳躍表

typedef struct zskiplist zskiplist;

跳躍表是有序集合的底層實現之一

跳躍表中的頭結點不計算在length長度之內,跳躍表的節點排序按照分值從小到大排序

每次建立新節點的時候,redis會根據冪次定律隨機生成乙個1-32的層數作為level陣列的大小,每個節點都有指向表尾方向的前進指標和之前表頭方向的後退指標,這兩個指標可以讓程式方便的遍歷所有節點,層的跨度用於記錄兩點之間的距離,跨度可以用來計算rank值.節點的分值是乙個double值,節點的物件是乙個指標,指向乙個儲存著sds字串的字串物件(下一節講redis物件)

資料結構

typedef struct intset intset;
顧名思義整數集合是用來儲存整數值的抽象資料結構

集合中不會出現重複元素

contents陣列中儲存的整數值有小到大排列

length等於contents的長度

雖然contents的定義是int8_t 但實際上contents的值型別由encoding決定

公升級當乙個新元素超過原來整數集合encoding定義的值的型別時,會進行公升級,公升級結果會使集合的encoding變成所有陣列中元素的值最大的資料型別,並且不支援降級

例如:有乙個整數集合[1,2,3],本身的編碼為int8,現在增加乙個300的數字進該集合,會導致集合的編碼公升級為int16,這個時候列表的大小由8x3=24 變為 16x4=64,即便int8可以儲存前三個值,但是為了簡單起見,仍然會為集合中每乙個元素分配同樣的空間

壓縮列表被用作列表鍵和雜湊鍵的底層實現

壓縮列表屬於特殊的結構,是一種資料儲存的方式,目的是為了節約記憶體,是一種採用特殊編碼的連續記憶體塊組成的順序型(sequential)資料結構.

大致結構如下:

zlbytes

zltail

zllen

entry1

entry2

...zlend

每個壓縮列表由如下三部分組成

previous_entry_length

encoding

content

前一節點的長度

記錄content的型別和長度

節點的值

如果前乙個節點長度小於254位元組,previous_entry_length會使用1位元組空間儲存這個長度,如果大於254位元組,將使用5位元組長度儲存這個值,這個機制會引起"連鎖更新"

連鎖更新: 假設現有連續的三個壓縮列表節點l1,l2,l3,長度分別為 253,253,253,現在往第乙個節點前新增乙個長度超過254的節點,這個時候l1要給previous_entry_length分配5個位元組來儲存長度,所以列表本身長度會變為257,這將導致l2也需要5位元組儲存l1的長度,l3也會產生同樣的變化,這樣由乙個列表操作引起的一系列更新操作成為連鎖更新

redis基本資料結構 1

redis的作者為了方便自己的使用,在redis中定義了動態字串sds,鍊錶,字典dict,跳躍表skiplist,整數集合intset和壓縮列表ziplist這六種資料結構。下文,我簡要地介紹一下幾種資料結構的定義。sds的全稱叫 dynamic string,它的定義和注釋如下 struct s...

redis基本資料結構概述

redis 有 5 種基礎資料結構,分別為 string 字串 list 列表 hash 雜湊 set 集合 和 zset 有序集合 以下圖示並不代表記憶體連續,僅僅只是邏輯表述。因為redis的key值為字串,當我們使用字串型別作為value時,我們是在將乙個字串對映另乙個字串。member是不可...

redis基本資料結構之ZSet

zset資料結構類似於set結構,只是zset結構中,每個元素都會有乙個分值,然後所有元素按照分值的大小進行排列,相當於是乙個進行了排序的鍊錶。如果zset是乙個鍊錶,而且內部元素是有序的,在進行元素插入和刪除,以及查詢的時候,就必須要遍歷鍊錶才行,時間複雜度就達到了o n 這個在以單執行緒處理的r...