-
字典
redis本身使用字典结构管理数据
-
redis使用hash表实现字典结构
- 使用了什么hash算法
- 使用SipHash算法,该算法能有效防止Hash表碰撞,并有不错的性能
- hash冲突怎么解决
- 使用链表法解决hash冲突
- hash表如何扩容
- 渐进式扩容,不会引起线程长期阻塞,redis字典扩容在每次操作数据的时候都执行一次单步扩容操作,将ht[0].table[rehashidx]的数据迁移到ht[1],再将ht[0]指向ht[1]
- 扩容条件
- hash表存储的键值对数量大于等于hash表数组的长度
- 开启了dict_can_resize或者负载因子大于dict_force_resize_ratio
- 扩容条件
- 渐进式扩容,不会引起线程长期阻塞,redis字典扩容在每次操作数据的时候都执行一次单步扩容操作,将ht[0].table[rehashidx]的数据迁移到ht[1],再将ht[0]指向ht[1]
- 使用了什么hash算法
-
hash扩容
ht[0] —> ht[1]
- 先找到ht[0]第一个非空索引位
- 遍历该索引位链表的所有元素
- 计算每个元素在ht[1]的hash表数组中的索引,将元素移动到ht[1]中
- 当ht[0]的used属性归于0时,则移动全部完成
- 释放ht[0].table,将ht[0]指针指向ht[1]
-
hash缩容
- 执行删除操作后redis会检查字典是否满足缩容(长度大于4&负载因子小于0.1)
-
编码
- 散列有两种编码类型:OBJ_ENCODING_HT和OBJ_ENCODING_ZIPLIST,使用dict和ziplist结构存储数据,优先使用ziplist存储数据,一个节点存储键,其后驱节点存储值,查找的时候遍历ziplist即可。
- 要使用ziplist存储元素需满足以下几个条件:
- 散列中所有的键和值的长度小于或等于server.hash_max_ziplist_value(通过hash-max-ziplist-value项配置)
- 散列中键值对的数量小于server.hash_max_ziplist_entries
- 要使用ziplist存储元素需满足以下几个条件:
- 散列有两种编码类型:OBJ_ENCODING_HT和OBJ_ENCODING_ZIPLIST,使用dict和ziplist结构存储数据,优先使用ziplist存储数据,一个节点存储键,其后驱节点存储值,查找的时候遍历ziplist即可。
-
4、集合
-
无序集合
redis通常使用字典结构保存集合数据,字典健存储集合元素,字典值为空。如果一个集合全为整数,使用字典就有点浪费了,redis使用intset保存。
- 插入元素到intset中
- 获取插入元素编码,如果插入元素编码级别高于intset编码,intset的编码则需要升级
- 通过二分查找插入元素是否为重复插入,是,则插入失败,否,则赋值
- 为intset重新分配内存空间(分配插入元素所需空间),若插入位置存在后驱节点,后驱节点全部后移
- 更新intset的len值
- intset升级编码
- 设置新的编码,然后分配新的内存空间
- 将intset的元素移动到新位置
- 然后插入新的元素
redis不会降级intset编码!
- 插入元素到intset中