redis0 1原始碼解析之字典

2021-10-06 10:47:01 字數 3150 閱讀 7548

字典也叫雜湊表。看一下redis中的實現。下面是資料結構關係圖。

redis中,雜湊表的設計思想是,申請乙個指標陣列,然後每個元素指向乙個鍊錶用來儲存資料(即鏈位址法)。

// 申請乙個表示字典的資料結構

dict *

dictcreate

(dicttype *type,

void

*privdataptr)

// 初始化字典資料結構

int_dictinit

(dict *ht, dicttype *type,

void

*privdataptr)

// 擴容

intdictresize

(dict *ht)

首先呼叫申請乙個dict結構體用來表示乙個字典。然後初始化他的相關字段,最後呼叫dictexpand開闢儲存資料的記憶體。

int

dictexpand

(dict *ht,

unsigned

long size)

}assert

(ht-

>used ==0)

;// 釋放舊的記憶體

_dictfree

(ht-

>table)

;// 覆蓋之前的資訊

*ht = n;

return dict_ok;

}

這樣就形成了乙個和文章開始那個圖一樣的結構。

int

dictadd

(dict *ht,

void

*key,

void

*val)

1 首先判斷key是否已經存在,存在的話就無法新增。

2 根據key和雜湊函式,計算對應的索引。

3 頭插法插入對應索引的鍊錶。

int

dictreplace

(dict *ht,

void

*key,

void

*val)

static

intdictgenericdelete

(dict *ht,

const

void

*key,

int nofree)

// 刪除這個節點

_dictfree

(he)

;// 已使用個數減一

ht->used--

;return dict_ok;

}// 儲存上乙個不匹配的

prevhe = he;

he = he-

>next;

}return dict_err;

/* not found */

}

首先根據key找到索引的對應的鍊錶,然後遍歷鍊錶找到key一樣的節點,最後就是從鍊錶中刪除乙個節點。

新增和刪除等操作都涉及到查詢元素,我們看看怎麼查詢。

dictentry *

dictfind

(dict *ht,

const

void

*key)

return

null

;}

我們可以看一下某個鉤子的實現。

// 雜湊函式

unsigned

intdictgenhashfunction

(const

unsigned

char

*buf,

int len)

// 比較函式

static

int_dictstringcopyhtkeycompare

(void

*privdata,

const

void

*key1,

const

void

*key2)

總來的流程就是根據key產生乙個索引,然後根據索引到雜湊表中取得對應的乙個鍊錶,然後操作這個鍊錶(新增,查詢,刪除)。

// 銷毀整個字典

int_dictclear

(dict *ht)

}/* free the table and the allocated cache structure */

// 釋放字典結構體

_dictfree

(ht-

>table)

;/* re-initialize the table */

// 重置字段

_dictreset

(ht)

;return dict_ok;

/* never fails */

}

該函式只是釋放字典裡儲存資料的記憶體,但是沒有釋放字典本身。下面函式可以釋放字典本身的記憶體。

// 釋放字典裡的資料和字典本身

void

dictrelease

(dict *ht)

7 迭代字典

redis中實現了各種迭代器對某種資料結構進行迭代,比如字典。

// 申請字典迭代器

dictiterator *

dictgetiterator

(dict *ht)

// 迭代字典的元素,每次呼叫返回乙個節點

dictentry *

dictnext

(dictiterator *iter)

else

// 還有節點,則同時記錄下乙個節,返回entry節點

if(iter-

>entry)

}return

null

;}

基本的邏輯就是,按照雜湊表陣列的索引,從小到大,每乙個索引,先去遍歷他對應的鍊錶,遍歷完後,繼續下乙個索引,直到最後乙個索引結束。

總結,redis的字典裡還有其他的一些方法,沒有一一枚舉。有興趣可以點這。

redis0 1原始碼解析之鍊錶

分析 之前先看看鍊錶的資料結構。新建乙個煉表頭結點 list listcreate void 釋放乙個鍊錶 void listrelease list list 釋放鍊錶記憶體 zfree list 3 插入乙個節點 支援頭插和尾插 給鍊錶新增乙個節點,頭插法 list listaddnodehea...

redis0 1原始碼解析之事件驅動

redis的事件驅動模組負責處理檔案和定時器兩種任務。下面是幾個函式指標 typedef void aefileproc struct aeeventloop eventloop,int fd,void clientdata,int mask typedef intaetimeproc struct...

Redis原始碼解析 字典結構

一般情況下,我們談到字典,難免要談到紅黑樹。但是redis這套字典庫並沒有使用該方案去實現,而是使用的是鍊錶,且整個 行數在1000行以內。所以這塊邏輯還是非常好分析的。我們可以想象下,如果使用普通的鍊錶去實現字典,那麼是不是整個資料都在一條鍊錶結構上呢?如果是這麼設計,插入和刪除操作是非常方便的,...