Redis数据结构---字典,哈希表,dict 或java中的map,数据使用key -> value的形式存储,整个redis数据库就是基于字典实现,api见hash

REDIS的hash实现原理和java的HashMap十分相似,可参考阅读

理解redis的hash实现,就要先理解一下三个结构  dictEntry, ditht, dict

哈希表节点 dictEntry {

void  *key //键值

union{void *val; uint64_tu64; int64_ts64} v  //值    可以是指针,可以是uint_64_t整数 或者int64_t整数

struct dictEntry *next;  //指向下一个哈希节点,形成链表的结构(同java hashmap中的entry)

}

哈希表 dictht{

dictEntry **table;  //一个元素为dictEntry 的数组

long size; // 哈希表的大小

long sizemask; // 哈希表大小掩码,用于计算存储时所在的数组下标  大小总是等于size-1

long used;  //当前哈希表已有的节点数量

}

哈希表有个负载因子 的概念,load_factor = used/size  即已使用 除以总数size的结果

而提供api给我们开发者,即直接使用的dict实现如下

字典 dict{

dictType *type //指针,特定类型的函数  redis中有定义,指向了一族函数,用以实现针对键值对的操作,这同list的dup free match一样,也是多太的一种,是dict可以存不同类型的键值对

void *privdata //私有数据  用以使用dictType中定义的特定函数时传入的可选参数

dictht ht[2]  //元素为哈希表的数组,长度为2,即保存着2个哈希表

in trehashidx // rehash索引,当不在进行rehash时为-1

}

当向一个dict中set一个键值A对时,会先使用hash算法根据键值计算出一个数字,即哈希表中数组的下标,该键值对就存放在此位置上,

如果再有一个键值B对被set存放进入此dict时,hash算法根据键值计算出的数字同上,即为键冲突,也叫哈希冲突,这时hash表会使用头插法,将B的dictEntry的next设置为A,形成链表的数据结构

随着dict的操作,键值对会有增多和减少,为了是负载因子在合理范围内,会产生rehash,其步骤简单如下:

当没有rehash的普通情况下,dict中的ht[2] 数组总是使用ht[0] 对应的哈希表来保存数据,当需要扩容或缩减时,会为ht[1]分配对应的存储空间,其大小算法是

扩容时,大小是第一个大于ht[0]的size的 2的n次方,缩小时,是第一个小于ht[0]长度的2的n次方(可参考java的Hashmap中的tablesizefor算法)

当ht[1]分配好空间后,会把ht[0]上的所有数据复制到ht[1]上,之后ht[0]变为空表,是否,把ht[1]移到ht[0]上继续使用

如果redis在执行BGSAVE或BAREWRITEAOF命令操作,会在当前redis服务现场中创建子进程,使用的是写时复制技术优化子进程的使用效率!

当没有子进程存在时,负载因子大于等于1时就会进行rehash,当存在子进程时,负载因子需要大于等于5才会进行rehash

当负载因子小于0.1时,也会进行收缩操作的rehash!

这样设计的目的就是尽量的使子进程工作期间,不要有rehash操作的产生,避免不必要的内存浪费

rehash使用的是渐进式rehash

它不会一次性的吧所有的ht[0] 中的数据一下子复制到ht[1]中,而是在增删改查操作发生时,每发生一次就复制一个值过去,同时对rehashidx做+1,避免了集中的大量的运算而导致redis夯死,值得注意的是,每次新增操作会把新增的值放入ht[1]中,同时复制一个ht[0]中数据到ht[1]中!同时,因为完整数据存在于2个hash表中,所有查询时是先查ht[0],再查ht[1]!循序渐进的复制,最终复制完成

redis--hash的实现的更多相关文章

  1. python处理json和redis hash的坑

    1.使用MySQLdb读取出来的数据是unicode字符串,如果要写入redis的hash中会变成 "{u'eth0_outFlow': 2.5, u'eth1_inFlow': 3.44} ...

  2. redis学习(二) Redis Hash

    Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象. Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿). redis ...

  3. redis hash map

    redis hash的使用详见文章:http://www.miaoyueyue.com/archives/235.html hash操作命令如下: hset(key, field, value):向名 ...

  4. ***Redis hash是一个string类型的field和value的映射表.它的添加、删除操作都是O(1)(平均)。hash特别适合用于存储对象

    http://redis.readthedocs.org/en/latest/hash/hset.html HSET HSET key field value   (存一个对象的时候key存) 将哈希 ...

  5. Redis hash数据类型操作

    Redis hash是一个string类型的field和value的映射表.一个key可对应多个field,一个field对应一个value.将一个对象存储 为hash类型,较于每个字段都存储成str ...

  6. Redis hash 类型及操作

    原文:http://blog.sina.com.cn/s/blog_5f044a4d0102v01k.html Redis hash是一个string类型的field和value的映射表.它的添加.删 ...

  7. Redis学习第三课:Redis Hash类型及操作

    Redis hash是一个string类型的field和value的映射表.它的添加.删除操作都是O(1)(平均).hash特别适用于存储对象.相较于对象的每个字段存在单个string类型.将一个对象 ...

  8. Python --Redis Hash操作

    一.Redis Hash操作 Redis 数据库hash数据类型是一个string类型的key和value的映射表,适用于存储对象.Redis 中每个 hash 可以存储 232 - 1 键值对(40 ...

  9. C#操作Redis Hash数据表

    /// <summary> /// Redis Hash /// </summary> public static void Redis_Hash() { RedisClien ...

  10. Redis hash(哈希)

    Redis hash可储存多个键值对,适合储存对象的属性. 1.hset key fieldName fileValue    //hset即hash set,set这里是设置的意思.往hash中添加 ...

随机推荐

  1. 010.Ansible_palybook 循环语句

    Ansible循环语句 1 简介 我们在编写playbook的时候,不可避免的要执行一些重复性操作,比如指安装软件包,批量创建用户,操作某个目录下的所有文件等.正如我们所说,ansible一门简单的自 ...

  2. Hutool :一个小而全的 Java 工具类库

    Hutool 简介 Hutool 是一个小而全的 Java 工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以"甜甜的 ...

  3. linux 系统监控命令之 top-(转自 Howie的专栏)

    top命令经常用来监控linux的系统状况,比如cpu.内存的使用,程序员基本都知道这个命令,但比较奇怪的是能用好它的人却很少,例如top监控视图中内存数值的含义就有不少的曲解. 本文通过一个运行中的 ...

  4. linux 创建网桥

    由于最近项目需验证个问题,需求是要创建一个虚拟机网桥,在使用ifconfig命令查看时让docker0网桥不在第一个显示,因此,我们创建一个虚拟网桥让它排在第一位置 项目使用Centos7系统,因此使 ...

  5. 3.21-22 od、tee

    3.21 od:按不同进制显示文件       od命令用于输出文件的八进制.十六进制或者其他格式编码的字节,通常用于显示或查看文件中不能直接显示在终端的字符.   -A 地址进制    按指定的进制 ...

  6. 优秀电路资料--- IOT方案

    完整的IOT方案 http://www.cirmall.com/circuit/4117/%E3%80%90%E5%BC%80%E6%BA%90%E3%80%91%E5%AE%8C%E6%95%B4% ...

  7. Python使用 Kubernetes API 访问集群

    通过将身份认证令牌直接传给 API 服务器,可以避免使用 kubectl 代理,像这样:使用 grep/cut 方式: 通过将身份认证令牌直接传给 API 服务器,可以避免使用 kubectl 代理, ...

  8. 程序员与年龄:四十岁普通开发、三十五岁首席架构、三十岁基层Leader

    最近,有一个词儿特别热门--躺平.有没有人跟你说过:"躺平说起来容易,做起来更容易." 和躺平相对的是另外一个词--内卷,群聊的时候,已经很多次看过草卷起来了.jpg表情包.某些节 ...

  9. Spring Mvc Long类型精度丢失

    背景 在使用Spring Boot Mvc的项目中,使用Long类型作为id的类型,但是当前端使用Number类型接收Long类型数据时,由于前端精度问题,会导致Long类型数据转换为Number类型 ...

  10. OpenCV 查找轮廓

    本文将结合实例代码,介绍 OpenCV 如何查找轮廓.获取边界框. 代码: contours.py OpenCV 提供了 findContours 函数查找轮廓,需要以二值化图像作为输入.并指定些选项 ...