欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)Dict的實(shí)現(xiàn)方法

 更新時(shí)間:2022年05月20日 15:00:54   作者:鳳瀾  
這篇文章主要介紹了Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)Dict的實(shí)現(xiàn)方法,本篇文章所述的dict在Redis中最主要的作用就是用于維護(hù)Redis數(shù)據(jù)庫中所有Key、value映射的數(shù)據(jù)結(jié)構(gòu),需要的朋友可以參考下

我們平時(shí)用Redis的時(shí)候,只是了解到了它對外的一些結(jié)構(gòu),如:string、list、set、hash、zset,但是我們卻很少能了解到Redis內(nèi)部用的存儲(chǔ)結(jié)構(gòu),小編將在這篇文章和大家秀一下Redis中的一個(gè)內(nèi)部結(jié)構(gòu)——dict。

一、dict是什么

不知道大家在用Redis的時(shí)候有沒有注意到,我們在使用大多數(shù)Redis命令的時(shí)候,都會(huì)讓你輸入一個(gè)key,后面才會(huì)讓你輸入具體的值。

我們本篇文章所述的dict在Redis中最主要的作用就是用于維護(hù)Redis數(shù)據(jù)庫中所有Key、value映射的數(shù)據(jù)結(jié)構(gòu),也就是我們在輸入set、zadd等命令時(shí)輸入的key與后面值的映射。321,上代碼。代碼來源(dict.h)。 如下代碼所示,dict結(jié)構(gòu)體里面有一個(gè)dictht 數(shù)組,dictht 里面的dictEntry 就是具體存放key、value映射關(guān)系的。

typedef struct dictEntry {
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    struct dictEntry *next;
} dictEntry;
typedef struct dictht {
    dictEntry **table;
    unsigned long size; //  hashtable 容量
    unsigned long sizemask;  // size -1
    unsigned long used;  // hashtable 元素個(gè)數(shù)   used / size =1
} dictht;
typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];// ht[0] , ht[1] =null
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    unsigned long iterators; /* number of iterators currently running */
} dict;

小貼紙:dictEntry 中用到了union聯(lián)合體這種結(jié)構(gòu)。也就是多個(gè)變量的結(jié)構(gòu)同時(shí)使用一塊內(nèi)存區(qū)域,區(qū)域的取值大小為該結(jié)構(gòu)中長度最大的變量的值。這有利于減少內(nèi)存碎片,提高內(nèi)存利用率,在Java中的壓縮指針技術(shù)就用到了聯(lián)合體。

二、dict數(shù)據(jù)結(jié)構(gòu)

1.結(jié)構(gòu)梳理

我們仔細(xì)看上面代碼中的結(jié)構(gòu),小編可以直接告訴你,其實(shí)它就是一個(gè)哈希表結(jié)構(gòu),在Java中相當(dāng)于一個(gè)HashMap,因?yàn)镽edis需要保證快速響應(yīng),所以選擇哈希表作為存儲(chǔ)結(jié)構(gòu)是一個(gè)不錯(cuò)的決定。我們這里只一起了解結(jié)構(gòu)中存具體數(shù)據(jù)的部分。

  • dictEntry:其實(shí)它就是一個(gè)鏈表結(jié)構(gòu),里面維護(hù)了key、value。
  • dictht :它維護(hù)了一個(gè)dictEntry 指針數(shù)組。 雖然我們?nèi)庋勰芸吹蕉x的是指針的指針,dictEntry **table。但其實(shí)指針的指針是指向了dictEntry 數(shù)組指針的首地址。Redis源碼里大多會(huì)這么用 table[index]。指針這塊有點(diǎn)繞,可以暫時(shí)直接認(rèn)為它就是一個(gè)指針數(shù)組。
  • dict: dict里面維護(hù)了一個(gè)dictht ht[2] 數(shù)組,相當(dāng)于兩個(gè)dictht 結(jié)構(gòu)。為什么要存兩個(gè)dictht 結(jié)構(gòu)呢。因?yàn)榧热皇枪1砟蔷鸵婕暗綌U(kuò)容,redis是單線程的,不可能一下子將所有的數(shù)據(jù)都轉(zhuǎn)移到新的哈希表中,這樣可能會(huì)造成服務(wù)長時(shí)間不可用,所以它退而求其次,選擇了"漸進(jìn)式擴(kuò)容"。

小貼紙:Redis中的漸進(jìn)式擴(kuò)容,采用的是在內(nèi)存中放置兩個(gè)哈希表結(jié)構(gòu),無需擴(kuò)容時(shí),使用的是哈希表0,在擴(kuò)容期間,將擴(kuò)容標(biāo)識(shí)設(shè)置為true,當(dāng)有新數(shù)據(jù)進(jìn)來的時(shí)候,發(fā)現(xiàn)正在擴(kuò)容,就會(huì)在將新數(shù)據(jù)直接放入哈希表1。而表0中的數(shù)據(jù)會(huì)在每次有請求命令并且請求的數(shù)據(jù)在表0中時(shí),將請求命令涉及到的數(shù)據(jù)直接掛到表1上。 在擴(kuò)容期間如果執(zhí)行查找命令會(huì)查找表0+表1的數(shù)據(jù)。

當(dāng)然,Redis如果一直不執(zhí)行命令的話。它也會(huì)有一個(gè)后臺(tái)定時(shí)任務(wù),對字典進(jìn)行主動(dòng)搬遷,它不會(huì)對未完成的事置之不理

// 服務(wù)器定時(shí)任務(wù)
void databaseCron() {
    ...
    if (server.activerehashing) {
        for (j = 0; j < dbs_per_call; j++) {
            int work_done = incrementallyRehash(rehash_db);
            if (work_done) {
                /* If the function did some work, stop here, we'll do
                 * more at the next cron loop. */
                break;
            } else {
                /* If this db didn't need rehash, we'll try the next one. */
                rehash_db++;
                rehash_db %= server.dbnum;
            }
        }
    }
}

2. 擴(kuò)容條件

  • 當(dāng)hash表中元素的個(gè)數(shù)等于數(shù)組長度時(shí),就會(huì)開始擴(kuò)容,擴(kuò)容的新數(shù)組是原數(shù)組的2倍。
  • 當(dāng)Redis發(fā)生其他情況沒有在元素個(gè)數(shù)等于數(shù)組長度時(shí)擴(kuò)容,那么Redis會(huì)有一個(gè)強(qiáng)制擴(kuò)容的條件,就是元素個(gè)數(shù)達(dá)到數(shù)組長度5倍時(shí)進(jìn)行強(qiáng)制擴(kuò)容。
/* Expand the hash table if needed */
static int _dictExpandIfNeeded(dict *d)
{
    /* Incremental rehashing already in progress. Return. */
    if (dictIsRehashing(d)) return DICT_OK;

    /* If the hash table is empty expand it to the initial size. */
    if (d->ht[0].size == 0) return dictExpand(d, DICT_HT_INITIAL_SIZE);

    /* 元素個(gè)數(shù)大于等于數(shù)組長度&&(能擴(kuò)容(bgsave時(shí)盡量不擴(kuò)容)或元素大于5倍時(shí)強(qiáng)制擴(kuò)容)
	 * static unsigned int dict_force_resize_ratio = 5;
	 */
    if (d->ht[0].used >= d->ht[0].size &&
        (dict_can_resize ||
         d->ht[0].used/d->ht[0].size > dict_force_resize_ratio))
    {
        return dictExpand(d, d->ht[0].used*2);
    }
    return DICT_OK;
}

3. 縮容條件

既然有擴(kuò)容,當(dāng)前就有縮容,要不占那么大內(nèi)存不是浪費(fèi)嗎?

  • 當(dāng)元素小于數(shù)組長度的10%時(shí)進(jìn)行縮容。
int htNeedsResize(dict *dict) {
    long long size, used;

    size = dictSlots(dict);
    used = dictSize(dict);
    return (size > DICT_HT_INITIAL_SIZE &&
            (used*100/size < HASHTABLE_MIN_FILL));
}

dict結(jié)構(gòu)的實(shí)現(xiàn)相對來說比較簡單,本文就介紹到這。

到此這篇關(guān)于Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)Dict的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)redis dict數(shù)據(jù)結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 玩轉(zhuǎn)Redis搭建集群之Sentinel詳解

    玩轉(zhuǎn)Redis搭建集群之Sentinel詳解

    這篇文章主要給大家介紹了關(guān)于Redis搭建集群之Sentinel的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • Redis實(shí)現(xiàn)商品秒殺的示例代碼

    Redis實(shí)現(xiàn)商品秒殺的示例代碼

    本文主要介紹了Redis實(shí)現(xiàn)商品秒殺的示例代碼,詳細(xì)介紹了Redis的List、Set和Hash類型,以及使用Redis事務(wù)保證原子性的方式,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-02-02
  • 基于Redis6.2.6版本部署Redis?Cluster集群的問題

    基于Redis6.2.6版本部署Redis?Cluster集群的問題

    這篇文章主要介紹了基于Redis6.2.6版本部署Redis?Cluster集群,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • Redis安裝及基本數(shù)據(jù)類型

    Redis安裝及基本數(shù)據(jù)類型

    這篇文章主要介紹了Redis安裝及基本數(shù)據(jù)類型,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • Redis解決庫存超賣問題實(shí)例講解

    Redis解決庫存超賣問題實(shí)例講解

    這篇文章主要介紹了Redis解決庫存超賣問題實(shí)例講解,問題和解決辦法都列舉了出來,很貼合實(shí)際開發(fā)場景,有需要的同學(xué)可以學(xué)習(xí)下
    2021-03-03
  • Redis源碼解析sds字符串實(shí)現(xiàn)示例

    Redis源碼解析sds字符串實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了Redis源碼解析sds字符串實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Redis批量刪除Key的三種方式小結(jié)

    Redis批量刪除Key的三種方式小結(jié)

    本文主要介紹了Redis批量刪除Key的三種方式小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 詳解利用redis + lua解決搶紅包高并發(fā)的問題

    詳解利用redis + lua解決搶紅包高并發(fā)的問題

    本篇文章主要介紹了利用redis + lua解決搶紅包高并發(fā)的問題 ,詳細(xì)的講訴了需求分析和方案,有興趣的可以了解一下。
    2016-11-11
  • Spring Boot 項(xiàng)目集成Redis的方式詳解

    Spring Boot 項(xiàng)目集成Redis的方式詳解

    這篇文章主要介紹了Spring Boot 項(xiàng)目集成Redis的方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧,需要的朋友可以參考下
    2021-08-08
  • Redis源碼分析之set?和?sorted?set?使用

    Redis源碼分析之set?和?sorted?set?使用

    本文介紹了Redis?中的?set?和?sorted?set?使用源碼實(shí)現(xiàn)分析,Redis?的?Set?是?String?類型的無序集合,集合成員是唯一的,sorted?set有序集合和集合一樣也是?string?類型元素的集合,對Redis?set?和?sorted?set使用相關(guān)知識(shí)感興趣的朋友一起看看吧
    2022-03-03

最新評論