本文为【Redis hash八股文合集】初版,后续还会进行优化更新,欢迎大家关注交流~
hello hello~ ,这里是绝命Coding——老白~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
💥个人主页:绝命Coding-CSDN博客
💥 所属专栏:后端技术分享
这里将会不定期更新有关后端、前端的内容,希望大家多多点赞关注收藏💖
往期内容(篇幅过多,不一一列出,感兴趣的小伙伴可以查看专栏):
大厂面试官问我:Redis处理点赞,如果瞬时涌入大量用户点赞(千万级),应当如何进行处理?【后端八股文一:Redis点赞八股文合集】-CSDN博客
大厂面试官问我:布隆过滤器有不能扩容和删除的缺陷,有没有可以替代的数据结构呢?【后端八股文二:布隆过滤器八股文合集】-CSDN博客
hash
相当于Java的HashMap,无序字典,内部实现结构上同Java的HashMap一致,也是 数组+链表
hash冲突就会用链表
redis中hash如果哈希冲突多,有什么办法改进
- 调整哈希函数: Redis 默认使用 MurmurHash2 算法作为哈希函数,这个算法在大多数情况下都能提供良好的散列分布。但如果发现特定的数据模式导致严重的哈希冲突,可以尝试使用其他哈希算法,比如 SHA-1 或 CRC32。
- 增大 hash table 的大小: Redis 的 hash table 是动态调整大小的,当冲突过多时可以显式地调用
HRESIZE
命令来增大 hash table 的大小,从而减少冲突。 - 使用 Redis 集群: Redis 集群模式下,key 会根据哈希值被自动分布到不同的节点上,有效地缓解了单机 hash table 的冲突问题。
Redis中hashmap数据类型的相关方法?
HSET/HMSET
: 设置 hash field 的值HGET/HMGET
: 获取 hash field 的值HDEL
: 删除 hash fieldHLEN
: 获取 hash 包含的 field 数量HKEYS/HVALS
: 获取所有 field 名称或值HGETALL
: 获取整个 hash 的所有 field 和值
Redis中hashmap类型的大键在集群情况下是否在多台机器上,还是单台机器上?
- 在 Redis 集群模式下,hash 的大 key 会根据 CRC16 hash 算法被分配到不同的分片(slot)上,也就是分散在不同的节点上。
- 这样可以更好地利用集群的存储和计算能力,提高整体的吞吐量和可扩展性。
- 对于单机 Redis,hash 的大 key 则都存储在同一台机器上。
Redis的哈希底层?
Redis 的哈希底层使用了一种叫做 "dict" 的哈希表数据结构来实现。
"dict" 由两个哈希表组成,主哈希表和备用哈希表。主哈希表用于存储数据,备用哈希表主要用于 rehash 操作。
每个哈希表由一个 dictht 结构体表示,包含了数组、已使用的槽数量、总槽数量等属性。
哈希算法使用 MurmurHash2,可以根据需要切换到其他算法如 SipHash。
Redis hash怎么存, 哈希冲突 扩容, 查询流程
(1)存储
- Redis 的 hash 数据类型底层使用 dict 结构来存储 key-value 对。
- 每个 hash 对应一个 dict,key 为 hash field,value 为对应的值。
- 当 hash 的 field 过多时,会自动扩容 dict 以减少冲突。
(2)解决哈希冲突
- Redis 使用拉链法来解决哈希冲突,即一个槽位下挂载一个链表存储所有冲突的键值对。
- 当冲突过多时,会自动对主哈希表进行 rehash 操作,把数据迁移到更大的哈希表中
(3)哈希表的扩容
- rehash 分为两个阶段:渐进式 rehash 和自动 rehash。
- 渐进式 rehash 会在每次查询/更新时,将一部分数据迁移到新的哈希表中。
- 当渐进式 rehash 完成后,会自动切换到新的哈希表,旧表被删除。
(4)查询流程
- 查询时,先根据 key 计算出 hash 值,定位到主哈希表的对应槽位。
- 遍历槽位下的链表,逐个比对 field 名称找到对应的值。
- 如果正在执行 rehash,还需要同时查询备用哈希表。
Redis为什么要这么用渐进式哈希来扩容
- 一次性 rehash 会导致短暂的服务中断,因为在 rehash 完成之前,无法处理任何请求。
- 渐进式 rehash 可以将 rehash 过程拆分成多个步骤,在处理正常请求的同时,逐步迁移数据到新的哈希表。
- 这样可以大大减少 rehash 过程对服务的影响,提高系统的可用性。
redis的hash渐进式扩容的触发条件
- Redis 会监控哈希表的负载因子(used_slots / total_slots),当主哈希表的负载因子超过阈值(1.0)时,会开始执行渐进式 rehash。
- 具体的阈值可以通过
hash-max-ziplist-entries
和hash-max-ziplist-value
配置参数来控制。 - 除了负载因子,Redis 也会根据当前的内存使用情况来决定是否需要触发 rehash。
渐进式 rehash 的过程
- Redis 会在处理每个请求时,顺带将主哈希表中的一个 entry 迁移到备用哈希表中。
- 这样可以将 rehash 过程分散到每个请求中,减少对服务的影响。
- 当备用哈希表的 entry 数量超过主哈希表的 50% 时,Redis 会切换到使用备用哈希表作为新的主哈希表。
Redis渐进式rehash过程中,每处理⼀个请求时,从哈希表1中的第 ⼀个索引位置开始,顺带着将这个索引位置上的所有entries拷贝到哈希表2中,这个请求是读请求还是写请求?
这个请求可以是读请求,也可以是写请求。
无论是读请求还是写请求,只要涉及到访问 hash 数据结构,Redis 都会进行这个渐进式迁移的动作。
如果渐进式时,这些的key突然都不访问了 会有什么问题
- 如果 hash 中的 key 在 rehash 期间完全没有访问,那么 rehash 的进度会非常缓慢。
- 为了解决这个问题,Redis 会在处理查询/更新请求时,优先将对应 key 所在槽位的数据迁移到新哈希表。
- 这样可以确保热点数据能够尽快完成迁移,提高 rehash 的效率。
为啥redis的rehash采用渐进式,而hashmap是一次性rehash
- Java 的 HashMap 采用一次性 rehash 是因为它是单机内存数据结构,不需要考虑服务可用性。
- 而 Redis 作为分布式缓存,需要在保证服务高可用的同时,完成动态扩容,所以采用了渐进式的 rehash 机制。
Redis中hashmap类型的大键在集群情况下是否在多台机器上,还是单台机器上?
- 在 Redis 集群模式下,hash 的大 key 会根据 CRC16 hash 算法被分配到不同的分片(slot)上,也就是分散在不同的节点上。
- 这样可以更好地利用集群的存储和计算能力,提高整体的吞吐量和可扩展性。
- 对于单机 Redis,hash 的大 key 则都存储在同一台机器上。
Redis的哈希底层?
Redis 的哈希底层使用了一种叫做 "dict" 的哈希表数据结构来实现。
"dict" 由两个哈希表组成,主哈希表和备用哈希表。主哈希表用于存储数据,备用哈希表主要用于 rehash 操作。
每个哈希表由一个 dictht 结构体表示,包含了数组、已使用的槽数量、总槽数量等属性。
哈希算法使用 MurmurHash2,可以根据需要切换到其他算法如 SipHash。
Redis hash怎么存, 哈希冲突 扩容, 查询流程
(1)存储
- Redis 的 hash 数据类型底层使用 dict 结构来存储 key-value 对。
- 每个 hash 对应一个 dict,key 为 hash field,value 为对应的值。
- 当 hash 的 field 过多时,会自动扩容 dict 以减少冲突。
(2)解决哈希冲突
- Redis 使用拉链法来解决哈希冲突,即一个槽位下挂载一个链表存储所有冲突的键值对。
- 当冲突过多时,会自动对主哈希表进行 rehash 操作,把数据迁移到更大的哈希表中
(3)哈希表的扩容
- rehash 分为两个阶段:渐进式 rehash 和自动 rehash。
- 渐进式 rehash 会在每次查询/更新时,将一部分数据迁移到新的哈希表中。
- 当渐进式 rehash 完成后,会自动切换到新的哈希表,旧表被删除。
(4)查询流程
- 查询时,先根据 key 计算出 hash 值,定位到主哈希表的对应槽位。
- 遍历槽位下的链表,逐个比对 field 名称找到对应的值。
- 如果正在执行 rehash,还需要同时查询备用哈希表。
Redis为什么要这么用渐进式哈希来扩容
- 一次性 rehash 会导致短暂的服务中断,因为在 rehash 完成之前,无法处理任何请求。
- 渐进式 rehash 可以将 rehash 过程拆分成多个步骤,在处理正常请求的同时,逐步迁移数据到新的哈希表。
- 这样可以大大减少 rehash 过程对服务的影响,提高系统的可用性。
redis的hash渐进式扩容的触发条件
- Redis 会监控哈希表的负载因子(used_slots / total_slots),当主哈希表的负载因子超过阈值(1.0)时,会开始执行渐进式 rehash。
- 具体的阈值可以通过
hash-max-ziplist-entries
和hash-max-ziplist-value
配置参数来控制。 - 除了负载因子,Redis 也会根据当前的内存使用情况来决定是否需要触发 rehash。
渐进式 rehash 的过程
(空间换时间的渐进式哈希)
- Redis 会在处理每个请求时,顺带将主哈希表中的一个 entry 迁移到备用哈希表中。
- 这样可以将 rehash 过程分散到每个请求中,减少对服务的影响。
- 当备用哈希表的 entry 数量超过主哈希表的 50% 时,Redis 会切换到使用备用哈希表作为新的主哈希表。
Redis渐进式rehash过程中,每处理⼀个请求时,从哈希表1中的第 ⼀个索引位置开始,顺带着将这个索引位置上的所有entries拷贝到哈希表2中,这个请求是读请求还是写请求?
这个请求可以是读请求,也可以是写请求。
无论是读请求还是写请求,只要涉及到访问 hash 数据结构,Redis 都会进行这个渐进式迁移的动作。
如果渐进式时,这些的key突然都不访问了 会有什么问题
- 如果 hash 中的 key 在 rehash 期间完全没有访问,那么 rehash 的进度会非常缓慢。
- 为了解决这个问题,Redis 会在处理查询/更新请求时,优先将对应 key 所在槽位的数据迁移到新哈希表。
- 这样可以确保热点数据能够尽快完成迁移,提高 rehash 的效率。
为啥redis的rehash采用渐进式,而hashmap是一次性rehash
- Java 的 HashMap 采用一次性 rehash 是因为它是单机内存数据结构,不需要考虑服务可用性。
- 而 Redis 作为分布式缓存,需要在保证服务高可用的同时,完成动态扩容,所以采用了渐进式的 rehash 机制。
后期新的八股文合集文章会继续分享,感兴趣的小伙伴可以点个关注~
更多精彩内容以及免费资料请关注公众号:绝命Coding