引言
简略温习一下,redis有哪些数据结构和对象。
数据结构
间断内存类
- SDS 简略动静字符串
- 整数汇合intset
- 压缩链表ziplist
随机内存类
- list和listnode
- zskiplist和zskiplistnode
- 间断+随机:dict、dictht和dictEntry
对象
总共有5种:
- string
- list
- hash
- set
- zset
其中,hash对象的外部实现是redis的字典,也就是dict构造,dict构造有两个字段和rehash无关:
- 两个hash表(hash表是dictht构造)
- rehashidx,记录rehash的进度
渐进式rehash
须要渐进式rehash的起因:
- 随着client对hash对象的增删数据操作,hash对象里的元素会相应的减少或缩小,导致内存利用率变低或减少hash碰撞几率,因而须要对其底层的哈希表进行扩缩容。扩缩容的规范是底层哈希表的负载因子;
- 扩缩容,须要相应地从新计算key在新的哈希表中的地位,这是一个耗费cpu算力的操作;
这就是渐进式rehash呈现的起因,rehash的需要加上一次性rehash的性能问题。
渐进式rehash触发的条件
分为扩容和缩容:
扩容,分为有没有正在执行bgsave(生成RDB文件)或bgrewriteaof命令(重写AOF)
- 正在执行,判断负载因子>=5
- 没有在执行,判断负载因子>=1
已知生成RDB文件或重写AOF也是比拟耗费cpu算力的操作,因而对这两个数值的不同,就能够了解了。
- 缩容:简略粗犷,负载因子<=0.1
附上负载因子计算公式:used / size (哈希表已应用的键数量/容量)
渐进式rehash的过程
参考:https://tech.meituan.com/2018...
在没有rehash时,dict构造外面的两个dichht构造,有一个的table指向的是空指针,即,这个样纸:
基于此状态形容渐进式rehash(扩容状况下)的过程:
- 为ht[1]调配一块新的内存,内存空间大小依照DICT_HT_INITIAL_SIZE * 2的n次方 >= h[0].used,这里>=的意思是第一个大于h[0].used的值;(在rehash过程中会始终维持这个内存耗费);
- 在rehash过程中,所有对h[0]的删改查操作,都会触发h[1]同样的操作,同时进行一次rehash,把h[0]的中h[0].table[rehashidx]地位的数据挪到h[1],而后给rehashidx+1;新增操作则会间接放到h[1]中;
- 每次rehash函数最初会判断h[0].used==0,if true,完结渐进式rehash过程。
参考:https://blog.csdn.net/weixin_...