C语言15天戏转redis —— 第四首 哈希对象类型

  redis中之hash也是咱们以受到的一再数据结构,它的构造基本上与编程语言中的HashTable,Dictionary大同小异,如果大家朝着后有啊逻辑需要用

Dictionary存放的话,可以根据气象优先考虑下redis哦,起码得装装逼嘛,现在本人默认你曾发出装逼的冲动了,打开redis手册,看看发生怎样我们所以收获

的装逼方法。

 

同一:常用方法

  只要是一个数据结构,最基础的恒久是CURD,redis中之insert和update,永远只有需要set来取代,比如下面的Hset,如下图:

C语言 1

眼前几篇稿子我还无选择一个计仔细讲解,其实呢没什么好教学的,就吓似C#遭到的一个类的一个方法而已,知道传递一些什么参数就OK了,就比如要

说之HSet,它的格式如下:

C语言 2

对接下自己于CentOS里面操作一下,

[administrator@localhost redis-3.0.5]$ src/redis-cli
127.0.0.1:6379> clear

127.0.0.1:6379> hset person name jack
(integer) 1
127.0.0.1:6379> hset person age 20
(integer) 1
127.0.0.1:6379> hset person sex famale
(integer) 1
127.0.0.1:6379> hgetall person
1) "name"
2) "jack"
3) "age"
4) "20"
5) "sex"
6) "famale"
127.0.0.1:6379> hkeys person
1) "name"
2) "age"
3) "sex"
127.0.0.1:6379> hvals person
1) "jack"
2) "20"
3) "famale"
127.0.0.1:6379> 

兴许有人看了面的console有好几迷惑,那就是前方有几乎独参数,比如person,name啦,然后才是value,如果您看了第一篇之言辞,你大概就是懂得了,

实质上以redis的之范围,它永远只生一个键,一个价,这个键永远都是字符串对象,也便是SDS对象,而值的品种就多矣,有字符串对象,有队列对象,

再有这首的hash对象,往后的不变聚集对象等等,如果您还免知晓的语句,转化为C#言语就是。

1 var person=new Dictionary<string,string>();
2 person.Add("name","jack");
3 ....

调用方法就是如此的简要,关键在于时不时的待您看一样禁闭手册,其实最紧要的凡探听下她于redis源码中之规律就是吓了。

 

其次:探索规律

  hash的源代码是在dict.h源代码里面,枚举如下:

typedef struct dictEntry {
    void *key;
    union {
        void *val;
        uint64_t u64;
        int64_t s64;
        double d;
    } v;
    struct dictEntry *next;
} dictEntry;

typedef struct dictType {
    unsigned int (*hashFunction)(const void *key);
    void *(*keyDup)(void *privdata, const void *key);
    void *(*valDup)(void *privdata, const void *obj);
    int (*keyCompare)(void *privdata, const void *key1, const void *key2);
    void (*keyDestructor)(void *privdata, void *key);
    void (*valDestructor)(void *privdata, void *obj);
} dictType;

/* This is our hash table structure. Every dictionary has two of this as we
 * implement incremental rehashing, for the old to the new 0. */
typedef struct dictht {
    dictEntry **table;
    unsigned long size;
    unsigned long sizemask;
    unsigned long used;
} dictht;

typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    int iterators; /* number of iterators currently running */
} dict;

/* If safe is set to 1 this is a safe iterator, that means, you can call
 * dictAdd, dictFind, and other functions against the dictionary even while
 * iterating. Otherwise it is a non safe iterator, and only dictNext()
 * should be called while iterating. */
typedef struct dictIterator {
    dict *d;
    long index;
    int table, safe;
    dictEntry *entry, *nextEntry;
    /* unsafe iterator fingerprint for misuse detection. */
    long long fingerprint;
} dictIterator;

地方就是是咱们用hash的源代码数据结构,接下自己来撸一撸其中的逻辑关系。

 

1. dict结构

1 typedef struct dict {
2     dictType *type;
3     void *privdata;
4     dictht ht[2];
5     long rehashidx; /* rehashing not in progress if rehashidx == -1 */
6     int iterators; /* number of iterators currently running */
7 } dict;

本条布局是hash的审的最底层数据结构,可以视中有5个特性。

 

<1> dictType *type

  
可以观看她的门类是dictType,从点你也可看出,它是来枚举结构定义之,如下:

1 typedef struct dictType {
2     unsigned int (*hashFunction)(const void *key);
3     void *(*keyDup)(void *privdata, const void *key);
4     void *(*valDup)(void *privdata, const void *obj);
5     int (*keyCompare)(void *privdata, const void *key1, const void *key2);
6     void (*keyDestructor)(void *privdata, void *key);
7     void (*valDestructor)(void *privdata, void *obj);
8 } dictType;

 

从上面这数据结构中君得视里边都是有些术,但是有一个要命重大的不二法门,那就是率先单hashFunction,可以见到它便是计算hash值的,

跟C#备受的dictionary中求hash值一样一样的。

C语言 3

 

<2> dictht ht[2]

     
 你可能会见疑窦,为什么这特性是2只轻重的数组呢,其实正真动的是ht[0],而ht[1]是用来扩容hash表时的暂存数组,这或多或少吧颇奇葩,

同时为深精妙,redis为什么会这样做啊???仔细思忖你可能会见掌握,扩容有些许栽方式,要么一次性扩容,要么渐进性扩容,后面这种扩容是什

么意思呢?就是我在扩容的同时不影响前端的CURD,我渐渐的拿多少由ht[0]转移到ht[1]屡遭,同时rehashindex来记录转移的图景,当尽移

得后,将ht[1]改成ht[0]使用,就这样简单。

 

  1. dicth结构

    1 typedef struct dictht {
    2 dictEntry **table;
    3 unsigned long size;
    4 unsigned long sizemask;
    5 unsigned long used;
    6 } dictht;

<1> dictEntry **table;

       从点是结构体中,你可看出一个颇关键之属性: dictEntry
**table, 其中table是一个屡屡组,数组类型是dictEntry,既然是一个反复组,

那么后的老三只属性就吓明了,size是屡屡组的轻重,sizemask和数组求模有关,used记录数组中已经运的大小,现在咱们将注意力放在dictEntry这

独数组实体类型方面。

 

  1. dictEntry结构

    1 typedef struct dictEntry {
    2 void key;
    3 union {
    4 void
    val;
    5 uint64_t u64;
    6 int64_t s64;
    7 double d;
    8 } v;
    9 struct dictEntry *next;
    10 } dictEntry;

打者数据结构上面你得看看有三只大属性。

率先只C语言就是是:   *key:它就是hash表中的key。

第二个就是:    union的*val 就是hash的value。

老三单就是是:    *next就是为着防备hash冲突采用的挂链手段。

此原理及C#遭逢的Dictionary还是同同的。

C语言 4

 

勿晓乃看明白了并未,如果总方描述的话,我可以描绘生如下的hash结构图。

C语言 5

哼了,就此打住,去公司了。