• 1.字典相关的几个结构体
  1. dicthash table存储key-value hash table数组每一个元素存放dictEntry链接的链表头结点,dictEntry节点存放key-value
  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;
  11.  
  12. typedef struct dictht {
  13. dictEntry **table; // 指向dictEntry数组的指针
  14. unsigned long size; //哈希表table的大小,初始化大小为4
  15. unsigned long sizemask; // size - 1 ,用来对hash值求与计算获得index
  16. unsigned long used; // 已经赋值了的数量
  17. } dictht;
  18.  
  19. typedef struct dict {
  20. dictType *type; // 方法
  21. void *privdata; // 保存key和value
  22. dictht ht[]; // hash table
  23. long rehashidx; // 如果rehashidx=-1表示没有进行rehash,如果如果rehashidx>-1,则表示正在进行rehash,搬运的位置是rehashidx
  24. int iterators; /* number of iterators currently running */
  25. } dict;
  • 2.动态扩容方法 int dictRehash(dict *d, int n)

   为了对dictht进行动态扩容,rehash方法将ht[0]中的值搬n个到ht[1]中, 分批次进行搬运,直到ht[0]中的值都搬到ht[1]上,再将ht[1]指针交给ht[0],rehashidx=-1,完成此次rehash过程

  1. int dictRehash(dict *d, int n) {
  2. int empty_visits = n * ; /* Max number of empty buckets to visit. */
  3. if (!dictIsRehashing(d)) return ;
  4.  
  5. // 从ht[0]中搬n个链表到ht[1]中
  6. while (n-- && d->ht[].used != ) {
  7. dictEntry *de, *nextde;
  8.  
  9. /* Note that rehashidx can't overflow as we are sure there are more
  10. * elements because ht[0].used != 0 */
  11. assert(d->ht[].size > (unsigned long) d->rehashidx);
  12. // 通过rehashidx可以接着从上一次搬完的位置开始搬
  13. while (d->ht[].table[d->rehashidx] == NULL) {
  14. d->rehashidx++;
  15. if (--empty_visits == ) return ;
  16. }
  17. de = d->ht[].table[d->rehashidx];
  18. /* Move all the keys in this bucket from the old to the new hash HT */
  19.  
  20. // 把ht[0]上的一个链表搬到ht[1]上
  21. while (de) {
  22. unsigned int h;
  23.  
  24. nextde = de->next;
  25. /* Get the index in the new hash table */
  26. h = dictHashKey(d, de->key) & d->ht[].sizemask;
  27. de->next = d->ht[].table[h];
  28. d->ht[].table[h] = de;
  29. d->ht[].used--;
  30. d->ht[].used++;
  31. de = nextde;
  32. }
  33. d->ht[].table[d->rehashidx] = NULL;
  34. d->rehashidx++;
  35. }
  36.  
  37. /* Check if we already rehashed the whole table... */
  38. if (d->ht[].used == ) {
  39. zfree(d->ht[].table);
  40. d->ht[] = d->ht[];
  41. _dictReset(&d->ht[]);
  42. d->rehashidx = -;
  43. return ;
  44. }
  45.  
  46. /* More to rehash... */
  47. return ;
  48. }
  • 3.使用到的几个hash算法

    1. 针对int的hash函数

      1. unsigned int dictIntHashFunction(unsigned int key) {
      2. key += ~(key << );
      3. key ^= (key >> );
      4. key += (key << );
      5. key ^= (key >> );
      6. key += ~(key << );
      7. key ^= (key >> );
      8. return key;
      9. }
    2. MurmurHash2算法

      1. unsigned int dictGenHashFunction(const void *key, int len) {
      2. /* 'm' and 'r' are mixing constants generated offline.
      3. They're not really 'magic', they just happen to work well. */
      4. uint32_t seed = dict_hash_function_seed;
      5. const uint32_t m = 0x5bd1e995;
      6. const int r = ;
      7.  
      8. /* Initialize the hash to a 'random' value */
      9. uint32_t h = seed ^len;
      10.  
      11. /* Mix 4 bytes at a time into the hash */
      12. const unsigned char *data = (const unsigned char *) key;
      13.  
      14. // 长度大于等于4的情况
      15. while (len >= ) {
      16. uint32_t k = *(uint32_t *) data; // 4*8=32, 取4个字节当作uint32
      17.  
      18. k *= m;
      19. k ^= k >> r;
      20. k *= m;
      21.  
      22. h *= m;
      23. h ^= k;
      24.  
      25. data += ;
      26. len -= ;
      27. }
      28.  
      29. /* Handle the last few bytes of the input array */
      30. // 剩下的长度小于4
      31. switch (len) {
      32. case :
      33. h ^= data[] << ;
      34. case :
      35. h ^= data[] << ;
      36. case :
      37. h ^= data[];
      38. h *= m;
      39. };
      40.  
      41. /* Do a few final mixes of the hash to ensure the last few
      42. * bytes are well-incorporated. */
      43. h ^= h >> ;
      44. h *= m;
      45. h ^= h >> ;
      46.  
      47. return (unsigned int) h;
      48. }
    3. djb hash算法
  1. unsigned int dictGenCaseHashFunction(const unsigned char *buf, int len) {
  2.  
  3. unsigned int hash = (unsigned int) dict_hash_function_seed;
  4. while (len--)
  5. hash = ((hash << ) + hash) + (tolower(*buf++)); /* hash * 33 + c */
  6. return hash;
  7. }   
  1. 细节前往
  2. (https://github.com/fangwendong/redis-learning/tree/master/struct/dict)
  1.  

redis源码学习-dict的更多相关文章

  1. Redis源码学习:字符串

    Redis源码学习:字符串 1.初识SDS 1.1 SDS定义 Redis定义了一个叫做sdshdr(SDS or simple dynamic string)的数据结构.SDS不仅用于 保存字符串, ...

  2. Redis源码学习:Lua脚本

    Redis源码学习:Lua脚本 1.Sublime Text配置 我是在Win7下,用Sublime Text + Cygwin开发的,配置方法请参考<Sublime Text 3下C/C++开 ...

  3. redis源码学习之slowlog

    目录 背景 环境说明 redis执行命令流程 记录slowlog源码分析 制造一条slowlog slowlog分析 1.slowlog如何开启 2.slowlog数量限制 3.slowlog中的耗时 ...

  4. 柔性数组(Redis源码学习)

    柔性数组(Redis源码学习) 1. 问题背景 在阅读Redis源码中的字符串有如下结构,在sizeof(struct sdshdr)得到结果为8,在后续内存申请和计算中也用到.其实在工作中有遇到过这 ...

  5. __sync_fetch_and_add函数(Redis源码学习)

    __sync_fetch_and_add函数(Redis源码学习) 在学习redis-3.0源码中的sds文件时,看到里面有如下的C代码,之前从未接触过,所以为了全面学习redis源码,追根溯源,学习 ...

  6. redis源码学习之工作流程初探

    目录 背景 环境准备 下载redis源码 下载Visual Studio Visual Studio打开redis源码 启动过程分析 调用关系图 事件循环分析 工作模型 代码分析 动画演示 网络模块 ...

  7. redis源码学习之lua执行原理

    聊聊redis执行lua原理 从一次面试场景说起   "看你简历上写的精通redis" "额,还可以啦" "那你说说redis执行lua脚本的原理&q ...

  8. redis源码之dict

    大家都知道redis默认是16个db,但是这些db底层的设计结构是什么样的呢? 我们来简单的看一下源码,重要的字段都有所注释 typedef struct redisDb { dict *dict; ...

  9. Redis源码学习-Master&Slave的命令交互

    0. 写在前面 Version Redis2.2.2 Redis中可以支持主从结构,本文主要从master和slave的心跳机制出发(PING),分析redis的命令行交互. 在Redis中,serv ...

随机推荐

  1. 使用Kotlin&Anko, 扔掉XML开发Android应用

    尝鲜使用Kotlin写了一段时间Android.说大幅度的减少了Java代码一点不夸张.用Java的时候动不动就new一个OnClickListener()匿名类,动不动就类型转换的地方都可以省下很多 ...

  2. shell脚本-成长之路

    我对shell脚本的认识,除了执行过同事写的shell 脚本外,其他一无所知,为了让自己强大,我决定自己研究shell脚本,也许在你看来很简答,没必要说这么多废话,但是我希望在我的技术log里记录下来 ...

  3. Codeforces Round #540 (Div. 3)--1118D1 - Coffee and Coursework (Easy version)

    https://codeforces.com/contest/1118/problem/D1 能做完的天数最大不超过n,因为假如每天一杯咖啡,每杯咖啡容量大于1 首先对容量进行从大到小的排序, sor ...

  4. kafka讲解

    转载http://www.jasongj.com/2015/01/02/Kafka深度解析 Kafka是Apache下的一个子项目,是一个高性能跨语言分布式发布/订阅消息队列系统,而Jafka是在Ka ...

  5. TBB的学习

    1. TBB简介 TBB ( Thread Building Blocks, 线程构建模块) 是Intel公司开发的并行编程开发的工具.它支持Windows,OS X, Linux平台,支持的编译器有 ...

  6. spring security文档地址

    https://docs.spring.io/spring-security/site/docs/4.1.0.RELEASE/reference/htmlsingle/

  7. Android-Java-封装

    先看一个未封装的Demo案例一: package android.java.oop03; class Person { int age; } public class PottingDemo { pu ...

  8. cnn公式推导

    CNN公式推导 1 前言 在看此blog之前,请确保已经看懂我的前两篇blog[深度学习笔记1(卷积神经网络)]和[BP算法与公式推导].并且已经看过文献[1]的论文[Notes on Convolu ...

  9. 获取用户真实ip

    public static string GetRealIP() { string result = System.Web.HttpContext.Current.Request.Headers[&q ...

  10. .net core 与ELK(3)安装Kibana

    1.去产品官网下载https://www.elastic.co/downloads/kibana 对应的tar.gz的压缩包,放到/usr/local/src目录 2.解压 -linux-x86_64 ...