redis hset hget字典的实现

操作命令

  • hset key不存在执行创建操作,存在执行更新操作
  • hsetnx key不存在才执行命令
  • hget 获取field上的value值
  • HINCRBY 加上多少数据,当value可以被解释成数字的情况
  • HINCRBYFLOAT增加浮点数
  • hstrlen 统计filed的value的长度
  • hexists key是否存在这个field
  • hdel 删除field,想删除key的话还是给用del删除key
  • hlen 统计key中filed的个数
  • hmset 给一个key设置多个filed
  • hkeys 获得key的所有filed值
  • hvals获得field的value值
  • hgetall field和value一起获得

一些原理知识

redis:6.2.1
dict位置: src/dict.h srcdict.c src/t_hash.c

字典采用渐进rehash的方式,哈希算法采用的murmurHashX算法(X表示版本号)。哈希因子 = used / size。

什么时候扩容?

  • redis服务器没有启动BGSAVE 或者 BGWRITEAOF命令的时候并且哈希因子>=1的时候
  • 开启上面命令,哈希因子>=5

因为这两个命令会开启子进程,而写时拷贝就会占用大量内存,这也是一个细节的优化

渐进哈希

查和新增的时候都会判断是否在rehash,如果是的话就会稍带从老的哈希表挪到新的哈希表中,稍带指得就是渐进rehash.rehash是把这个哈希表的索引后面的链表都挪到新的哈希表上面去。找索引给10次机会,如果10次机会都用完还没找到合适的机会就会返回了。
在这里插入图片描述

源码

这部分源码还可以,都能看懂,介绍一下这些struct成员变量吧都是在src/dich.h能找到的

dict这是个字典,type可以理解为回调函数。privdata暂时没有用到,dictht就是两块哈希表表。rehashidx不等于1的时候说明在渐进rehash中,rehashidx意为在第一块哈希表中哈希到那里的下标。pauserehash看名字猜测是判断是否终止了渐进哈希。

typedef struct dict {
    
    
    dictType *type;// 设置哈希函数的
    void *privdata;
    dictht ht[2];// 两块哈希表
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    int16_t pauserehash; /* If >0 rehashing is paused (<0 indicates coding error) */
} dict;

dictht table就是存放key-value的了,size是开辟容量,sizemash = size - 1用作哈希值的计算。used包含了多少元素,包括了开链法的拥有的元素

typedef struct dictht {
    
    
    dictEntry **table;
    unsigned long size;
    unsigned long sizemask;
    unsigned long used;
} dictht;

dictType存放那一系列函数指针了

typedef struct dictType {
    
    
    uint64_t (*hashFunction)(const void *key);// 获得hash值
    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);
    int (*expandAllowed)(size_t moreMem, double usedRatio);// 扩容
} dictType;

在t_hash.c文件中我们可以看到我们经常使用的hset、hget的使用。void hsetCommand(client *c),暂时能力有限刚接触源码就大致看懂了。因为最开始很好奇hset这个的field是怎么存的,今天终于知道了
key还是保存在哈希表里,而val还是一个哈希表,val->key就是field字段了,而val->val就是存放val了。

猜你喜欢

转载自blog.csdn.net/dxgzg/article/details/121715183