聊聊 Redis 分片集群
Posted writeline
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了聊聊 Redis 分片集群相关的知识,希望对你有一定的参考价值。
❝今天继续来聊一聊 Redis 里的分片集群。
❞
实际上分片集群原理很大程度上依赖于和。而分片集群相比这两种来说,它更多的是为了解决写的扩展能力。
1.负载均衡
当我们尝试搭建一台具有三主三从的分片集群时,首先我们能想到的是,三台主节点在做存储的时候,该选择哪一台呢?我们可以想象一下nginx
的负载策略,有
-
随机轮询 -
加权轮询 -
最小连接数 -
hash -
等等
但由于分片集群的特殊性,因为我们要存储数据。假设你选择随机抑或是最小连接数,那这个特性会实时变化,显然当数据存储进去后,下一次在获取就可能获取不到了。所以,这几种不可取的。而 hash 策略不错,我们常用于数据分表。而 hash 策略又可分为
-
简单哈希 -
一致性哈希 -
哈希槽
1.1 简单哈希
Hash(key) % 3
这个算法很简单,对master
的数量做取模运算。但缺点很明显,当某个节点增加或移除后,路由方式发生变化,会造成大面积的数据无法访问到。而我们常说的缓存击穿正是这个问题。
1.2 一致性哈希
很显然,一致性哈希正是为了解决简单哈希的问题。首先,它不在直接对master
数量做取模运算了,而是对2^32次方做取模,值的范围在[0,2^32-1]。一致性哈希将范围抽象成一个圆环,使用哈希算法计算出来的哈希值会落在圆环上。然后我们的master
实例也会分布在圆环上,在圆环上沿着顺时针方向查找,这样便完成了一次的 key 的分配。如下图假设现在有 A、B、C 三个实例按照如图所示的位置分布在圆环上,此时计算出来的 hash 值,取模之后位置落在了位置D,那么我们按照顺时针的顺序,就能够找到我们这个 key 应该分配的实例B。同理如果我们计算出来位置在E,那么对应选择的实例就是A。即使这个时候实例 B 挂了,也不会影响到实例 A 和 C 的数据,也就是它的影响面就比较小,只有 B 节点会受影响。但是一致性哈希也有个问题,就是数据倾斜和数据不平衡问题。如下图此时数据落在节点 A 上的概率明显是大于其他两个节点的,其次落在节点 C 上的概率最小。这样一来会导致整个集群的数据存储不平衡,AB 节点压力较大,而 C 节点资源利用不充分。为了解决这个问题,一致性哈希算法引入了「虚拟节点机制」。
1.3 哈希槽
哈希槽算法与一致性哈希算法类似,分片集群将自己分成了 16384 个Slot(槽位)。通过 CRC16 算法计算出来的哈希值会跟 16384 取模,取模之后得到的值就是对应的槽位,然后每个节点都会负责处理一部分的槽位,就像下表这样。
节点 | 处理槽位 |
---|---|
A | 0 - 5000 |
B | 5001 - 10000 |
C | 10001 - 16383 |
我们知道,Redis
最终是采用哈希槽的方案。在我们了解了相应的负载算法后,我们可以在继续来聊下Redis
如何进行自动扩缩容?
2.自动扩缩容
为什么要说这个扩缩容呢?我们都知道,分片集群扩展的是写的能力,而根据哈希槽算法,每个节点会负责一部分的槽位,当节点上线,槽位必须要重新分配,不然就无法体现写的扩展能力了。而当节点下线,槽位也是必须要重新分配的,不然原先节点负责的槽位就没有节点负责了。而Redis
是通过 reshard 来实现的。这个是Redis
内部自己管理的,对于使用者来说并不需要去关注。
3.高可用及故障转移
这和模式相似,就不多做介绍了。
4.集群间节点通信机制
集群元数据的维护,一般有
-
集中式 -
分散式
而我们知道Redis
使用的分散式的模式。
4.1 集中式
这个模式顾名思义,就是所有元数据的维护交由某个节点。优点是对于读取和维护变得简单,缺点就是某个节点压力较大。
4.2 分散式
Redis
使用了名为「gossip」的协议。中文解释为流言,八卦。这个模式同样的,也是顾名思义,每个节点都维护着一份节点信息,而他们之间要不断的同步,以此来达到一致的状态。优缺点和集中式的正好相反。
4.3 简单了解下 gossip 协议
协议间通信的端口是 10000 + Redis
节点通信端口,例如 6379。那它又包含了那些消息类型呢?如下表
消息类型 | 消息内容 |
---|---|
MEET | 给某个节点发送MEET消息,请求接收消息的节点加入到集群中 |
PING | 每隔一秒钟,选择5个最久没有通信的节点,发送PING消息,检测对应的节点是否在线;同时还有一种策略是,如果某个节点的通信延迟大于了cluster-node-time的值的一半,就会立即给该节点发送PING消息,避免数据交换延迟过久 |
PONG | 当节点接收到MEET或者PING消息之后,会反馈一个PONG消息给发送方,代表自己收到了MEET或者PING消息。同时,节点也可以主动的通过PONG消息向集群中广播自己的信息,让其他节点获取到自己最新的属性,就像完成了故障转移之后新的master向集群发送PONG消息一样 |
FAIL | 用于广播自己的对某个节点的宕机判断,假设当前节点对A节点判断为宕机,就会立即向Redis Cluster广播自己对于A节点的判断,所有收到消息的节点就会对A节点做标记 |
PUBLISH | 用于向指定的Channel发送消息,某个节点收到PUBLISH消息之后会直接在集群内广播,这样一来,客户端无论连接到任何节点都能够订阅这个Channel |
通过这个表格我们可以知道,这个协议对 Redis 来说有这么几点好处
-
易扩展 -
节点非常容易增加或减少 -
高度容错 -
因为元数据是分散,挂掉了某几台后,元数据依然是完整的 -
健壮性也比较好
❝本篇分享先到这里,欢迎关注。
❞
以上是关于聊聊 Redis 分片集群的主要内容,如果未能解决你的问题,请参考以下文章
在 Istio 中实现 Redis 集群的数据分片读写分离和流量镜像