Redis学习 —— 分片Hash算法
一、前言
在现今的后端开发中,缓存中间的已经成为必不可少的一部分。但是作为中间件必然有其性能的瓶颈。而解决这一问题的解决的方式就是
构建Redis集群水平扩展Redis。
那么如何保证Redis结点增删后依旧保持原KEY依然可以访问原有结点,就是一个绕不开的问题。
一、问题复现,机器数取模HASH算法
- 介绍
每一个key算出一个数值,之后由这个数值对当前Redis节点个数进行取模预算,算出该key应该属于哪一台机器。hash = key%n。 - 问题
因为 n 与Redis的机器数紧密相关,只有少量数据经过HASH算法后仍可以保证与原有一致。对于Redis集群的架构来说几乎不可用。
二、解决方案
-
一致性Hash算法
- 介绍
一致性Hash算法规定每一个key计算hash的规则是一致的,全部对2^32 - 1进行取模。但是Redis设备本身也有一个HASH值也是通过这个方式计算得出。当key的hash算出后,会将此数据放入比此hash值大的第一个设备上。 - 画图
如图一个HASH环,环上的每一个点代表一个对2^32-1取模的hash值,现在存在Node-A和Node-B两个结点。
如果一个数据的key经过hash之后的结果为[1231238-99898]区间(自动取模),该数据将会放到Node-A,如果为[99899-1231239]的数据将会放到Node-B中。
- 问题
仍然会存在Redis的结点增删时会有数据依然会算错,但是随着Redis结点的增加这种影响会逐渐减小。因为每次只会有一台Redis的数据存取出现混乱。
- 介绍
-
哈希槽算法
-
介绍
Hash槽算法,核心思想是将Hash与Redis结点剥离开。每一个key经过HASH算法之后会对应一个HASH槽,将槽放入哪一个Redis结点,该数据就放到哪一个Redis结点中。 -
画图
hash槽大小为16384,每一个数据计算时先同一个CRC16计算在对16384进行取模。之后就16384个槽分配给Redis结点。当扩容之后相同的key计算完HASH后,直接找槽即可。
-
问题
完全解决因为Redis结点动态扩容会产生数据存取不一致的问题,也是现在Redis(6.0.6+)的解决方案。但是通过联想可以得知算法也必定会有额外的开销,本文不在深入讨论了。
-
三、总结
本文着重数据存储是否存在的混乱的角度进行思考,在本写的时候选用的HASH算法为哈希槽算法。
但是hash算法主要看重他的思想,通过这种HASH算法在其他的中间件也是通用的,比如MQ的hash计算方案。