【Redis学习笔记】聊聊Redis的高可用性 (High Usability)(上)
这个系列是个人学习Redis的一点记录,希望对大家有帮助
若有错误,欢迎指正
我们为什么需要高可用性?
我们知道,Redis作为一个内存数据库,自然在物理层面上就奠定其高性能的基础,也就是常说的QPS(Queries Per Second)很高。
由于是内存数据库,其高效能的背后也有当机的风险,学过一点计算机组成原理的,或是对计算机硬件稍有了解的朋友,应该都对内存的特性不陌生------断电清空内容。
有人抬杠说,我们Redis有RDB(Redis Database)和AOF(Append Only File)这样的持久化方案,何必害怕当机,数据存在文件里了。
这一点光就今天讨论的可用性来说,无可厚非。但是倘若我们在生产中,如在把redis作为社交app的缓存之类的场景下,一旦当机,redis进程反复请求I/O,系统效能必定下降(谁又希望在刷微博的时候等上30s呢?)。
因此,我们必须找到一个在性能与可用性之间兼得的方案。
什么是高可用?
John Carnell在《Spring Microservice In Action》中如此描述高可用:
需要能够支持 “热”集群环境,…可以跨多个节点共享。如果一个节点变得不可用,集群中的其他节点应该能够接管工作
从这句话中,可以窥见高可用性的概念无非三点:
- 热集群:实时更新同步热数据,每个节点内部的数据都不过时。
- 共享:集群内的信息互通有无,比如,一个节点当机,集群内其他节点应该都会收到消息。
- 接管工作:集群内节点当机(master)时,应该上一个替补(slave),并且这个替补能够完全接管当机节点之前的工作。
Redis的高可用
Redis作为一个成熟的,被广泛使用的分布式的,KV型的NoSQL产品,以上的特性自然是被很好地实现了,我们由简至繁地来看看Redis的方案吧。
简单实现:Redis主从模式
Redis的主从模式之所以被认为是简单实现,是因为其虽然实现了其所谓的高可用性的 三点,但是其方式,或者说带给开发人员和运维人员的体验是地狱一般的,如果这种数据库产品有“豆瓣评分”,我会给 3/10
。
主从模式很简单,就是设置一个redis的主节点(master)给他配置两个从节点(slave)
主节点拥有与客户端(Client)的交互权(读/写),而从节点只能根据主节点的数据或者变化进行拷贝、更新,或是被客户端读(read-only)。
(客户端可以认为是Jedis、Redis Desktop Manager、redis-cli等等)
接下来就是这个主从模式反人类的地方了:
这是主节点宕机的场景,这个场景下,运维人员要做的是:
- 把一个从节点(slave)升为主节点(master)
- 将其他从节点的拷贝地址转移到新的主节点上
- 客户端更新修改主节点地址
而这一切,都要手动完成
试想,这是在阿里的机房里,并且此时正好是双十一购物节。
好吧,我已经看到运维和架构师在写辞呈了。
不光如此,这种传统的主从模式还有其他弊端:
-
主节点性能被捆绑在单个机器上,写的性能和储存能力受单个机器拖累,单机性能提升成本较大,且容易发生边际效应递减。
-
备份时永远以主节点为准,无论是增加新的key,还是修改value,都需要 从节点 向 主节点 作备份,此时,如果发生同步中断,从节点 会请求全量同步,在大项目下,必然导致毫秒级甚至秒级的卡顿,这是产品经理和用户难以接受的。
-
当然在全量同步时还会发生其他问题,这里不再展开,请参考这里
Sentinel架构(Redis哨兵模式)
既然主从模式是对运维的考验,那么,我们(Redis开发者们)就得对症下药,把运维的双手解放出来,专心于维护核心业务,而不是来维护轮子。
哨兵
Redis开发者们引入了哨兵(Sentinel)机制,所谓哨兵,即运行在服务器上的哨兵进程。
哨兵进程,是一种监控进程,有点像Netflix Eureka的监控机制,它们每隔一段时间向Redis节点们作一次检查。(如每隔十秒发送PING包,或者叫心跳包)
(实际上,上图也呈现了,哨兵节点之间也存在监控关系,使得哨兵服务本身更加健壮。)
回到高可用,哨兵模式又是如何实现以上几条原则的呢?
“热”集群
热集群的实现,与传统主从模式几乎无差,无非是主从拷贝的那一套。
共享
这里的共享涉及到三类对象:
- Redis节点
- 哨兵节点
- 客户端
比如,主节点一旦有故障,哨兵节点发送的PING包会timeout(见计算机网络ICMP - PING指令原理),随后,哨兵节点通知其他节点(其他Redis节点、其他哨兵以及客户端)
接管工作
Sentinel模式的好处就是,主从更换是由程序自动执行的(运维落泪)
那么,既然是自动更换,就要定下规则,要按照基本法、选举法,去产生…
我们不如把这个Redis的集群的运作看作是一场模拟政治游戏
master是现任总统,slave是两位副总统。
现在总统(Master)不再能够胜任自己的职务,需要议会(哨兵集群Sentinel Group)作一个弹劾仲裁。
当有一位议员(哨兵)同意弹劾,我们称作主观下线(Subjective Down)。
当半数以上的议员(哨兵)同意弹劾,我们称其为客观下线(Objective Down)。
根据所谓 “民主” 的精神,需要半数以上的议员同意弹劾,才能启动弹劾程序。
弹劾过程必须公平公开公正,弹劾后必须通知全体成员。(客户端、从节点、其他哨兵)
主观下线与客观下线
tip:
- 主观下线既针对主节点,也针对从节点
- 客观下线只针对主节点
主观下线: 此时有一个哨兵节点对某个主/从节点的PING包超时,该哨兵分享消息到其他节点,此时不采取接管措施。
客观下线: 上面讲了,标记了主节点为主观下线的哨兵节点,会通知其他哨兵节点,当标记了主观下线的哨兵达到一定数量 quorum
时,主节点将被认为是客观下线(此时对于发送PING包的频率也会随之提高)
授权: 当存在客观下线的情况,我们不能立刻开始“弹劾程序”,需要一定数量的授权majority of the Sentinels
才能开始。
接管
国不可一日无圣,弹劾完总统后,就要选出一个临时总统,人选自然是从 slaves 里来。
议员们需要通过某种流程,同时选出一个议员来执行这一项弹劾决议。(选出一个哨兵来通知从节点和新的主节点更新配置)
其中一个Sentinel 将通知被选上的从节点,这个消息也要公开。
接下来就是被弹劾的总统与临时总统的工作交接了。(新的主节点更改配置,从节点向新的主节点作备份复制)
仍然有问题
虽然哨兵模式消除了运维人员手动维护节点接管的的痛点,但是仍然不能解决上面提到的几个问题:
- 哨兵模式本身只是在主从模式上增加哨兵的特性,并不能解决单机存储带来的性能瓶颈。
- 哨兵模式增加的哨兵本身就是一种资源上的开销,以实现自动化运维。
- 全量同步问题上仍然是鸵鸟姿态(不解决),并且系统的伸缩性存在严重问题。
总结
主从模式是对高可用的一种可行实现,而哨兵模式本质上就是一种自上而下的优化------能解决一部分问题,但是没能抓住本质。
若是在高突发高并发的场景下,如何才能真正地提高性能呢?那可能需要一点破坏性创新。
下期会介绍 Redis Cluster集群模式。
文中的政治体制与时政新闻,请不要对号入座,谢谢
参考致谢
https://blog.****.net/weixin_30329623/article/details/95551492
https://juejin.im/post/6844904191236767751
https://www.cnblogs.com/Eugene-Jin/p/10819601.html
https://redis.io/topics/sentinel
https://juejin.im/entry/6844903766534127624
GOOD LUCK ! ! !