redis如何做到高可用
一个slave节点如果挂掉了,是不会影响可用性的,因为还有其他的slave在提供相同数据下的相同的对外查询服务。但是,如果master节点挂掉了,没办法写入数据,写缓存的时候,全部失效,那slave节点就没办法复制数据,系统就相当于不可用了。
redis的高可用架构,叫做 failover
故障转移,也可以叫做主备切换。
master节点在故障时,自动检测,并且将某个slave节点自动切换为master节点的过程,叫做主备切换。这个过程,实现了redis的主从架构的高可用。
哨兵的功能
- 集群监控:负责监控redis master和slave进程是否正常工作。
- 消息通知:如果某个redis实例有故障,那么哨兵会负责发送消息作为报警通知给管理员。
- 故障转移:如果master节点挂掉了,就自动转移到slave节点上。
- 配置中心:如果故障转移发生了,通知客户端新的master地址。
哨兵用于实现redis集群的高可用,本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。
- 故障转移的时候,判断一个master节点是否宕机,需要大部分的哨兵都同意才行,涉及到分布式选举的问题。
- 即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的,因为如果一个作为高可用机制重要组成部分的故障转移系统本身是单点的,那就很坑爹了。
哨兵的核心知识
- 哨兵至少需要3个实例,来保证自己的健壮性。
- 哨兵+redis主从的部署架构,是不保证数据零丢失的,只能保证redis集群的高可用。
- 对于哨兵+redis主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行充足的测试和演练。
redis哨兵主备切换的数据丢失问题
异步复制导致的数据丢失
因为master节点是异步复制数据至slave节点的,所以在还未复制的时候,一部分数据写入至master节点,此时master节点因为一些原因发生了故障导致宕机了,那写入到master节点但还未复制到slave节点的数据,就会丢失了。
脑裂导致的数据丢失
某个master节点突然脱离正常的网络,跟其他的slave机器不能进行网络通信,但是实际上master还运行着。此时,哨兵集群可能会认为master宕机了,所以开启选举,将其他的slave切换成了master。这个时候,集群里就会有两个master,这就是所谓的脑裂。
此时虽然某个slave被切换成了master,但是可能client还没来得及切换到新的master,还是继续向旧的master写入数据。在旧master重新恢复之后,会被当作一个slave挂到新的master上去,自己的数据会被清空,重新从新的master中复制数据。因为新的master没有后来client写入的数据,所以这部分的数据也就丢失了。
数据丢失问题的解决方法
进行如下配置
// 要求至少有1个slave,数据复制 和 同步的延迟不能超过10秒
// 如果说一旦所有的slave,数据复制 和 同步的延迟超过了10秒,此时的master就不会接收任何请求
min-slaves-to-write 1
min-slaves-max-lag 10
减少异步复制数据的丢失
有了 min-slaves-max-lag
这个配置,可以确保说,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太大了,就拒绝客户端写入请求。这样可以把master宕机时部分数据未同步到slave导致的数据丢失降低在可控范围。
针对那些拒绝的请求,可以放入消息队列当中,每隔10分钟慢慢消费写入缓存。或者将拒绝的请求先写入本地缓存,等待哨兵选举了新的master之后,再同步给新的master节点。
减少脑裂的数据丢失
如果一个master出现脑裂,跟其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求。因此再脑裂场景下,最多就丢失10秒的数据。
sdown和odown转换机制
sdown:主观宕机,如果一个哨兵觉得master宕机了,就是主观宕机。
odown:客观宕机,如果quorum数量的哨兵都觉得master宕机了,就是客观宕机。
如果一个哨兵ping一个master,超过了 is-master-down-after-milliseconds
指定的毫秒数,就会主观认为master宕机了(sdown)。
如果一个哨兵在指定时间内,收到了quorum数量的其他哨兵也认为master是sdown的,那么就认为是客观宕机(odown)。
哨兵集群的自动发现机制
slave配置的自动纠正
slave->master的选举算法
如果一个master节点被认为是odown了,而且又majority数量 的哨兵都允许主备切换,那么某个哨兵就会执行主备切换操作,首先会选举一个slave来,考虑slave的一些信息:
- 跟master断开连接的时长
如果一个slave跟master断开连接的时间已经超过了 down-after-millseconds
的10倍,外加master宕机市场,那么slave就会被认为不适合选举为master。
- slave的优先级
slave priority越低,优先级越高。
- 复制offset
如果slave priority相同,那么看replica offset,哪个slave复制了越多的数据,offset越靠后,优先级越高。
- run id
如果上面的两个条件相同,那么选择run id比较小的slave。