不想谈好吉他的撸铁狗,不是好的程序员,欢送微信关注「SH 的全栈笔记」
前言
上文咱们聊了基于 Sentinel 的 Redis 高可用架构,理解了 Redis 基于读写拆散的主从架构,同时也晓得当 Redis 的 master 产生故障之后,Sentinel 集群是如何执行 failover 的,以及其执行 failover 的原理是什么。
这里大略再提一下,Sentinel 集群会对 Redis 的主从架构中的 Redis 实例进行监控,一旦发现了 master 节点宕机了,就会选举出一个 Sentinel 节点来执行故障转移,从原来的 slave 节点中选举出一个,将其晋升为 master 节点,而后让其余的节点去复制新选举进去的 master 节点。
你可能会感觉这样没有问题啊,甚至可能满足咱们生产环境的应用需要了,那咱们为什么还须要 Redis Cluster 呢?
为什么须要 Redis Cluster
确实,在 数据 上,有 replication 正本做保障;可用性 上,master 宕机会主动的执行 failover。
那问题在哪儿呢?
首先 Redis Sentinel 说白了也是基于 主从复制,在主从复制中 slave 的数据是齐全来自于 master。
假如 master 节点的内存只有 4G,那 slave 节点所能存储的数据下限也只能是 4G。而且在之前的追随杠精的视角一起来理解 Redis 的主从复制文章中也说过,主从复制架构中是读写拆散的,咱们能够通过减少 slave 节点来扩大主从的读并发能力,然而 写能力 和存储能力 是无奈进行扩大的,就只能是 master 节点可能承载的下限。
所以,当你只须要存储 4G 的数据时候的,基于主从复制和基于 Sentinel 的高可用架构是齐全够用的。
然而如果当你面临的是海量的数据的时候呢?16G、64G、256G 甚至 1T 呢?当初互联网的业务外面,如果你的体量足够大,我感觉是必定会面临缓存 海量 缓存数据的场景的。
这就是为什么咱们须要引入Redis Cluster。
Redis Cluster 是什么
晓得了为什么须要 Redis Cluster 之后,咱们就能够来对其一探到底了。
那什么是 Redis Cluster 呢?
很简略,你就能够了解为 n 个主从架构组合在一起对外服务。Redis Cluster 要求至多须要 3 个 master 能力组成一个集群,同时每个 master 至多须要有一个 slave 节点。
这样一来,如果一个主从可能存储 32G 的数据,如果这个集群蕴含了两个主从,则整个集群就可能存储 64G 的数据。
咱们晓得,主从架构中,能够通过减少 slave 节点的形式来扩大读申请的并发量,那 Redis Cluster 中是如何做的呢?尽管每个 master 下都挂载了一个 slave 节点,然而在 Redis Cluster 中的读、写申请其实都是在 master 上实现的。
slave 节点只是充当了一个数据备份的角色,当 master 产生了宕机,就会将对应的 slave 节点提拔为 master,来从新对外提供服务。
节点负载平衡
晓得了什么是 Redis Cluster,咱们就能够持续上面的探讨了。
不晓得你思考过一个问题没,这么多的 master 节点。我存储的时候,到底该抉择哪个节点呢?个别这种负载平衡算法,会抉择 哈希算法。哈希算法是怎么做的呢?
首先就是对 key 计算出一个 hash 值,而后用哈希值对 master 数量进行取模。由此就能够将 key 负载平衡到每一个 Redis 节点下来。这就是简略的 哈希算法 的实现。
那 Redis Cluster 是采取的下面的哈希算法吗?答案是 没有。
Redis Cluster 其实采取的是相似于 一致性哈希 的算法来实现节点抉择的。那为什么不必哈希算法来进行实例抉择呢?以及为什么说是相似的呢?咱们持续探讨。
因为如果此时某一台 master 产生了宕机,那么此时会导致 Redis 中 所有的缓存生效。为什么是所有的?假如之前有 3 个 master,那么之前的算法应该是 hash % 3,然而如果其中一台 master 宕机了,则算法就会变成 hash % 2,会影响到之前存储的所有的 key。而这对缓存前面爱护的 DB 来说,是致命的打击。
什么是一致性哈希
晓得了通过传统哈希算法来实现对节点的负载平衡的弊病,咱们就须要进一步理解 什么是一致性哈希。
咱们下面提过哈希算法是对 master 实例数量来取模,而 一致性哈希 则是对 2^32 取模,也就是值的范畴在[0, 2^32 -1]。一致性哈希将其范畴形象成了一个圆环,应用 CRC16 算法计算出来的哈希值会落到圆环上的某个中央。
而后咱们的 Redis 实例也散布在圆环上,咱们在圆环上依照顺时针的程序找到第一个 Redis 实例,这样就实现了对 key 的节点调配。咱们举个例子。
假如咱们有 A、B、C 三个 Redis 实例依照如图所示的地位散布在圆环上,此时计算出来的 hash 值,取模之后地位落在了 地位 D ,那么咱们依照顺时针的程序,就可能找到咱们这个 key 应该调配的 Redis 实例 B。同理如果咱们计算出来地位在 E,那么对应抉择的 Redis 的实例就是 A。
即便这个时候 Redis 实例 B 挂了,也不会影响到实例 A 和 C 的缓存。
例如此时节点 B 挂了,那之前计算出来在地位 D 的 key,此时会依照顺时针的程序,找到节点 C。相当于主动的把原来节点 B 的流量给转移到了节点 C 下来。而其余本来就在节点 A 和节点 C 的数据则齐全不受影响。
这就是一致性哈希,可能在咱们后续须要新增节点或者删除节点的时候,不影响其余节点的失常运行。
虚构节点机制
然而一致性哈希也存在本身的小问题,例如当咱们的 Redis 节点散布如下时,就有问题了。
此时数据落在节点 A 上的概率显著是大于其余两个节点的,其次落在节点 C 上的概率最小。这样一来会导致整个集群的数据存储不均衡,AB 节点压力较大,而 C 节点资源利用不充沛。为了解决这个问题,一致性哈希算法引入了 虚构节点机制。
在圆环中,减少了对应节点的虚构节点,而后实现了虚构节点到实在节点的映射。假如当初计算得出了地位 D,那么依照顺时针的程序,咱们找到的第一个节点就是C #1,最终数据理论还是会落在节点 C 上。
通过减少虚构节点的形式,使 ABC 三个节点在圆环上的地位更加平均,均匀了落在每一个节点上的概率。这样一来就解决了上文提到的数据存储存在不平均的问题了,这就是一致性哈希的虚构节点机制。
Redis Cluster 采纳的什么算法
下面提到过,Redis Cluster 采纳的是类一致性哈希算法,之所以是 类一致性哈希算法 是因为它们实现的形式还稍微有差异。
例如一致性哈希是对 2^32 取模,而 Redis Cluster 则是对 2^14(也就是 16384)取模。Redis Cluster 将本人分成了 16384 个Slot(槽位)。通过 CRC16 算法计算出来的哈希值会跟 16384 取模,取模之后失去的值就是对应的槽位,而后每个 Redis 节点都会负责解决一部分的槽位,就像下表这样。
节点 | 解决槽位 |
---|---|
A | 0 – 5000 |
B | 5001 – 10000 |
C | 10001 – 16383 |
每个 Redis 实例会本人保护一份 slot – Redis 节点 的映射关系,假如你在节点 A 上设置了某个 key,然而这个 key 通过 CRC16 计算出来的槽位是由节点 B 保护的,那么就会提醒你须要去节点 B 上进行操作。
Redis Cluster 如何做到高可用
不晓得你思考过一个问题没,如果 Redis Cluster 中的某个 master 节点挂了,它是如何保障集群本身的高可用的?如果这个时候咱们集群须要扩容节点,它该负责哪些槽位呢?咱们一个一个问题的来看一下。
集群如何进行扩容
咱们开篇聊过,Redis Cluster 能够很不便的进行横向扩容,那当新的节点退出进来的时候,它是如何获取对应的 slot 的呢?
答案是通过reshard(从新分片)来实现。reshard 能够将曾经调配给某个节点的任意数量的 slot 迁徙给另一个节点,在 Redis 外部是由 redis-trib 负责执行的。你能够了解为 Redis 其实曾经封装好了所有的命令,而 redis-trib 则负责向获取 slot 的节点和被转移 slot 的节点发送命令来最终实现 reshard。
假如咱们须要向集群中退出一个 D 节点,而此时集群内曾经有 A、B、C 三个节点了。
此时 redis-trib 会向 A、B、C 三个节点发送迁徙出槽位的申请,同时向 D 节点发送筹备导入槽位的申请,做好筹备之后 A、B、C 这三个源节点就开始执行迁徙,将对应的 slot 所对应的键值对迁徙至指标节点 D。最初 redis-trib 会向集群中所有主节点发送槽位的变更信息。
高可用及故障转移
Redis Cluster 中保障集群高可用的思路和实现和 Redis Sentinel 一模一样,感兴趣的能够去看我之前写的对于 Sentinel 的文章 Redis Sentinel- 深入浅出原理和实战。
简略来说,针对 A 节点,某一个节点认为 A 宕机了,那么此时是 主观宕机 。而如果集群内超过半数的节点认为 A 挂了,那么此时 A 就会被标记为 主观宕机。
一旦节点 A 被标记为了主观宕机,集群就会开始执行 故障转移。其余失常运行的 master 节点会进行投票选举,从 A 节点的 slave 节点中选举出一个,将其切换成新的 master 对外提供服务。当某个 slave 取得了超过半数的 master 节点投票,就胜利入选。
入选胜利之后,新的 master 会执行 slaveof no one
来让本人进行复制 A 节点,使本人成为 master。而后将 A 节点所负责解决的 slot,全副转移给本人,而后就会向集群发 PONG 音讯来播送本人的最新状态。
依照 一致性哈希 的思维,如果某个节点挂了,那么就会沿着那个圆环,依照顺时针的程序找到遇到的第一个 Redis 实例。
而对于 Redis Cluster,某个 key 它其实并不关怀它最终要去到哪个节点,他只关怀他最终落到哪个 slot 上,无论你节点怎么去迁徙,最终还是只须要找到对应的 slot,而后再找到 slot 关联的节点,最终就可能找到最终的 Redis 实例了。
那这个 PONG 音讯又是什么货色呢?别急,上面就会聊到。
简略理解 gossip 协定
这就是 Redis Cluster 各个节点之间替换数据、通信所采纳的一种协定,叫做gossip。
gossip: 谰言、八卦、小道消息
gossip 是在 1989 年的论文上提出的,我看了一堆材料都说的是 1987 年发表的,然而文章里的工夫明确是 1989 年 1 月份发表。
感兴趣的能够去看看 Epidemic Algorithms for Replicated . Database Maintenance,在过后提出 gossip 次要是为了解决在分布式数据库中,各个正本节点的数据同步问题。但随着技术的倒退,gossip 后续也被宽泛使用于信息扩散、故障探测等等。
Redis Cluster 就是利用了 gossip 来实现本身的 信息扩散 的。那应用 gossip 具体是如何通信的呢?
很简略,就像图里这样。每个 Redis 节点 每秒钟 都会向其余的节点发送 PING,而后被PING 的节点会回一个PONG。
gossip 协定音讯类型
Redis Cluster 中,节点之间的音讯类型有 5 种,别离是 MEET、PING、PONG、FAIL 和 PUBLISH。这些音讯别离传递了什么内容呢?我简略总结了一下。
音讯类型 | 音讯内容 |
---|---|
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 |
应用 gossip 的优劣
既然 Redis Cluster 抉择了 gossip,那必定存在一些 gossip 的长处,咱们接下来简略梳理一下。
长处 | 形容 |
---|---|
扩展性 | 网络能够容许节点的任意减少和缩小,新减少的节点的状态最终会与其余节点统一。 |
容错性 | 因为每个节点都持有一份残缺元数据,所以任何节点宕机都不会影响 gossip 的运行 |
健壮性 | 与容错性相似,因为所有节点都持有数据,位置平台,是一个去中心化的设计,任何节点都不会影响到服务的运行 |
最终一致性 | 当有新的信息须要传递时,音讯能够疾速的发送到所有的节点,让所有的节点都领有最新的数据 |
gossip 能够在 O(logN) 轮就能够将信息流传到所有的节点,为什么是 O(logN)呢?因为每次 ping,以后节点会带上本人的信息外加整个 Cluster 的 1 /10 数量的节点信息,一起发送进来。你能够简略的把这个模型形象为:
你转发了一个特地有意思的文章到朋友圈,而后你的敌人们都感觉还不错,于是就一传十、十传百这样的散播进来了,这就是朋友圈的 裂变流传。
当然,gossip 依然存在一些毛病。例如音讯可能最终会通过很多轮能力达到指标节点,而这可能会带来较大的提早。同时因为节点会随机选出 5 个最久没有通信的节点,这可能会造成某一个节点同时收到 n 个反复的音讯。
总结
总的来说,Redis Cluster 相当于是把 Redis 的 主从架构 和Sentinel集成到了一起,从 Redis Cluster 的高可用机制、判断故障转移以及执行故障转移的过程,都和主从、Sentinel 相干,这也是为什么我在之前的文章里说,主从是 Redis 高可用架构的基石。
好了以上就是本篇博客的全部内容了,如果你感觉这篇文章对你有帮忙,还麻烦 点个赞 , 关个注 , 分个享 , 留个言。
欢送微信搜寻关注【SH 的全栈笔记】,查看更多相干文章
举荐浏览:
- Redis 根底 - 分析根底数据结构及其用法
- 浅谈 JVM 和垃圾回收
- Redis Sentinel- 深入浅出原理和实战
- 追随杠精的视角一起来理解 Redis 的主从复制
- 简略理解 InnoDB 底层原理