Redis中的数据分片问题

1.前言

单个redis节点使用,最大问题是物理瓶颈为:

  • 内存容量
  • 读写效率(吞吐量,单位时间读写的数据量)

为了解决上述问题,启动redis集群。

2.Redis集群

2.1集群需要考虑的是无论客户端采用何种方式,何种算法,连接使用redis,保证数据读写的单调性(key-value 在哪写的,就要在哪读)。

为了保证单调性,所以要引入算法,将系统生成的大量数据,切分到了多个redis节点---数据切分分片出现。

Redis中的数据分片问题

 2.2hash取余

hash取余是非常经典的数据分片的计算逻辑.

hash取余的一种公式(java中可以轻松实现):

当使用三个节点,需要决定数据存储在哪里时,使用hash取余可以对key值左计算,映射绑定其中一个节点,从而,当去读key值的时候,照样找到同样的节点。

计算公式:(key.hashCode()&Integer.MAX_VALUE)%N

公式说明:

N:是数据分片的个数

key.hashCode(): 对key做hash散列计算,只要key值不变,得到一个不变可正可负的整数.只要散列计算,能够做到key不变,整数结果不变,不一定非得使用hashCode 最终任意一个key值都会对应[-21亿,21亿]区间的一个整数

key.hashCode()&Integer.MAX_VALUE: 31位二进制保真运算,目的是将前面的整数保真后31位二进制,保证他是一个正整数.& 位的与运算.目的是取得一个正整数

取得正整数的方法还有取绝对值,但是绝对值计算特别慢,所以采用位与运算

结论1:当key值不变时,可以得到一个不变的正整数

(key.hashCode()&Integer.MAX_VALUE)%N

N=5,取余结果 [0,1,2,3,4]

N=4,取余结果 [0,1,2,3]

N=3,取余结果 [0,1,2]

对N取余 结果[0,1,2,3,4,5…,N-1]

结论2:当key值不变时,可以通过hash取余得到 [0,1,2,..,N-1] 一个不变的取余结果

hash取余就可以应用在redis分布式数据分片计算逻辑中

当有key-value出现时,先对key做hash取余 n是节点个数(现在是3)

所有节点jedis排序(list) 0 1 2 … n-1 使用到取余结果对应到一个固定的jedis对象,最终连接固定的redis节点

hash取余算法缺点 :

  • 只要是hash必定数据倾斜; 可以通过key值的设计解决数据倾斜,key越规律,数据倾斜越小. 
  • 由于redis集群有动态线性扩展的特点.3个变5个,5个变12个,很频繁发生.hash取余无法保证扩容,缩容时的单调性.(单调性造成严重破坏) 

Redis中的数据分片问题

在一个频繁发生扩容缩容的分布式结构中,hash取余不适用,但是N不发生变化的结构中总是使用hash取余

一致性hash :
jedis中,封装了一种对应分布式的分片计算逻辑--一致性hash,在redis集群做分布式扩容和缩容时,虽然也会影响数据的单调性,但是节点越多,影响的数据量越小.