Redis主从集群切换数据丢失的解决方案

一、数据丢失的情况

异步复制同步丢失

集群产生脑裂数据丢失

1.异步复制丢失

对于Redis主节点与从节点之间的数据复制,是异步复制的,当客户端发送写请求给master节点的时候,客户端会返回OK,然后同步到各个slave节点中。

如果此时master还没来得及同步给slave节点时发生宕机,那么master内存中的数据会丢失;

要是master中开启持久化设置数据可不可以保证不丢失呢?答案是否定的。在master 发生宕机后,sentinel集群检测到master发生故障,重新选举新的master,如果旧的master在故障恢复后重启,那么此时它需要同步新master的数据,此时新的master的数据是空的(假设这段时间中没有数据写入)。那么旧master中的数据就会被刷新掉,此时数据还是会丢失。

2.集群产生脑裂

首先我们需要理解集群的脑裂现象,这就好比一个人有两个大脑,那么到底受谁来控制呢?在分布式集群中,分布式协作框架zookeeper很好的解决了这个问题,通过控制半数以上的机器来解决。

那么在Redis中,集群脑裂产生数据丢失的现象是怎么样的呢?

假设我们有一个redis集群,正常情况下client会向master发送请求,然后同步到salve,sentinel集群监控着集群,在集群发生故障时进行自动故障转移。

此时,由于某种原因,比如网络原因,集群出现了分区,master与slave节点之间断开了联系,sentinel监控到一段时间没有联系认为master故障,然后重新选举,将slave切换为新的master。但是master可能并没有发生故障,只是网络产生分区,此时client任然在旧的master上写数据,而新的master中没有数据,如果不及时发现问题进行处理可能旧的master中堆积大量数据。在发现问题之后,旧的master降为slave同步新的master数据,那么之前的数据被刷新掉,大量数据丢失。

在了解了上面的两种数据丢失场景后,我们如何保证数据可以不丢失呢?在分布式系统中,衡量一个系统的可用性,我们一般情况下会说4个9,5个9的系统达到了高可用(99.99%,99.999%,据说淘宝是5个9)。对于redis集群,我们不可能保证数据完全不丢失,只能做到使得尽量少的数据丢失。

二、如何保证尽量少的数据丢失?

在redis的配置文件中有两个参数我们可以设置:

min-slaves-to-write 1
min-slaves-max-lag 10

min-slaves-to-write默认情况下是0,min-slaves-max-lag默认情况下是10。

以上面配置为例,这两个参数表示至少有1个salve的与master的同步复制延迟不能超过10s,一旦所有的slave复制和同步的延迟达到了10s,那么此时master就不会接受任何请求。

我们可以减小min-slaves-max-lag参数的值,这样就可以避免在发生故障时大量的数据丢失,一旦发现延迟超过了该值就不会往master中写入数据。

那么对于client,我们可以采取降级措施,将数据暂时写入本地缓存和磁盘中,在一段时间后重新写入master来保证数据不丢失;也可以将数据写入kafka消息队列,隔一段时间去消费kafka中的数据。

通过上面两个参数的设置我们尽可能的减少数据的丢失,具体的值还需要在特定的环境下进行测试设置。

补充:Redis Cluster 会丢数据吗?

Redis Cluster 不保证强一致性,在一些特殊场景,客户端即使收到了写入确认,还是可能丢数据的。

场景1:异步复制

client 写入 master B

master B 回复 OK

master B 同步至 slave B1 B2 B3

B 没有等待 B1 B2 B3 的确认就回复了 client,如果在 slave 同步完成之前,master 宕机了,其中一个 slave 会被选为 master,这时之前 client 写入的数据就丢了。

wait 命令可以增强这种场景的数据安全性。

wait 会阻塞当前 client 直到之前的写操作被指定数量的 slave 同步成功。

wait 可以提高数据的安全性,但并不保证强一致性。

因为即使使用了这种同步复制方式,也存在特殊情况:一个没有完成同步的 slave 被选举为了 master。

场景2:网络分区

6个节点 A, B, C, A1, B1, C1,3个master,3个slave,还有一个client,Z1。

发生网络分区之后,形成了2个区,A, C, A1, B1, C1 和 B Z1。

这时 Z1 还是可以向 B 写入的,如果短时间内分区就恢复了,那就没问题,整个集群继续正常工作,但如果时间一长,B1 就会成为所在分区的 master,Z1 写入 B 的数据就丢了。

maximum window(最大时间窗口) 可以减少数据损失,可以控制 Z1 向 B 写入的总数:

过去一定时间后,分区的多数边就会进行选举,slave 成为 master,这时分区少数边的 master 就会拒绝接收写请求。

这个时间量是非常重要的,称为节点过期时间。

一个 master 在达到过期时间后,就被认为是故障的,进入 error 状态,停止接收写请求,可以被 slave 取代。

小结

Redis Cluster 不保证强一致性,存在丢失数据的场景:

异步复制

在 master 写成功,但 slave 同步完成之前,master 宕机了,slave 变为 master,数据丢失。

wait 命令可以给为同步复制,但也无法完全保证数据不丢,而且影响性能。

网络分区

分区后一个 master 继续接收写请求,分区恢复后这个 master 可能会变为 slave,那么之前写入的数据就丢了。

可以设置节点过期时间,减少 master 在分区期间接收的写入数量,降低数据丢失的损失。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • Redis cluster集群模式的原理解析

    redis cluster redis cluster是Redis的分布式解决方案,在3.0版本推出后有效地解决了redis分布式方面的需求 自动将数据进行分片,每个master上放一部分数据 提供内置的高可用支持,部分master不可用时,还是可以继续工作的 支撑N个redis master node,每个master node都可以挂载多个slave node 高可用,因为每个master都有salve节点,那么如果mater挂掉,redis cluster这套机制,就会自动将某个slave

  • Redis Cluster集群主从切换的踩坑与填坑

    因为项目的原因采用了Redis Cluster,3主3从,每台主机1主1从,集群信息如下: 10.135.255.72:20011> cluster nodes 7b662b36489a6240aa21d1cf7b04b84019254b63 10.135.255.74:20012 slave 85c78164a448fb9965e22447429a56cab226c68f 0 1537239581900 43 connected 61c3e1a640e71f4801d850c901dd33f0

  • 使用Docker搭建Redis主从复制的集群

    在主从复制模式的集群里,主节点一般是一个,从节点一般是两个或多个,写入主节点的数据会被复制到从节点上,这样一旦主节点出现故障,应用系统能切换到从节点去读写数据,这样能提升系统的可用性.而且如果再采用主从复制模式里默认的读写分离的机制,更能提升系统的缓存读写性能.所以对性能和实时性不高的系统而言,主从复制模式足以满足一般的性能和安全性方面的需求. 1 概述主从复制模式 在实际应用中,如果有相应的设置,在向一台Redis服务器里写数据后,这个数据可以复制到另外一台(或多台)Redis服务器,这里数据

  • 通过Docker部署Redis 6.x集群的方法

    系统环境: Redis 版本:6.0.8 Docker 版本:19.03.12 系统版本:CoreOS 7.8 内核版本:5.8.5-1.el7.elrepo.x86_64 一.什么是 Redis 集群模式 在 Redis 3.0 版本后正式推出 Redis 集群模式,该模式是 Redis 的分布式的解决方案,是一个提供在多个 Redis 节点间共享数据的程序集,且 Redis 集群是去中心化的,它的每个 Master 节点都可以进行读写数据,每个节点都拥有平等的关系,每个节点都保持各自的数据和

  • Redis主从集群切换数据丢失的解决方案

    一.数据丢失的情况 异步复制同步丢失 集群产生脑裂数据丢失 1.异步复制丢失 对于Redis主节点与从节点之间的数据复制,是异步复制的,当客户端发送写请求给master节点的时候,客户端会返回OK,然后同步到各个slave节点中. 如果此时master还没来得及同步给slave节点时发生宕机,那么master内存中的数据会丢失: 要是master中开启持久化设置数据可不可以保证不丢失呢?答案是否定的.在master 发生宕机后,sentinel集群检测到master发生故障,重新选举新的mast

  • 基于Docker搭建Redis主从集群的实现

    最近陆陆续续有不少园友加我好友咨询 redis 集群搭建的问题,我觉得一定是之前写的这篇 <基于Docker的Redis集群搭建> 文章有问题了,所以我花了几分钟浏览之前的文章总结了下面几个问题: redis 数量太少,只创建了 3 个实例:由于只有 3 个实例,所以全部只能是主节点,无法体现集群主从关系:如何搭建主从集群?如何分配从节点? 基于之前的文章,我想快速的过一下这几个问题,本文基于 Docker + Redis 5.0.5 版本,通过 cluster 方式创建一个 6 个 redi

  • Redis整合MySQL主从集群的示例代码

    目录 1.用Docker搭建MySQL主从集群 1.1 拉取mysql镜像 1.2 创建配置文件夹 1.3 编写主服务器的配置文件信息 1.4 启动mysql主服务器的容器 1.5 观察主服务器状态 1.6 配置mysql从服务器 1.7 启动mysql从服务器 1.8 确认主从关系 2.准备数据 2.1 创建数据库 2.2 创建student数据表 2.3 向student表插入几条数据 3.用Java代码读写MySQL集群和Redis 3.1 引入redis和mysql依赖 3.2 代码整合

  • Redis Cluster集群收缩主从节点详细教程

    目录 1.Cluster集群收缩概念 2.将6390主节点从集群中收缩 2.1.计算需要分给每一个节点的槽位数 2.2.分配1365个槽位给192.168.81.210的6380节点 2.3.分配1365个槽位给192.168.81.220的6380节点 2.4.分配1365个槽位给192.168.81.230的6380节点 2.5.查看当前集群槽位分配 3.验证数据迁移过程是否导致数据异常 4.将下线的主节点从集群中删除 4.1.删除节点 4.2.调整主从交叉复制 4.3.当节点存在数据无法删

  • 玩转Redis搭建集群之Sentinel详解

    前言 Redis作为内存数据库,需要具备高可用的特点,不然如果服务器宕机,还在内存里的数据就会丢失.我们最常用的高可用方法就是搭建集群,master机器挂了,可以让slave机器顶上,继续提供服务.但是Redis集群是不会自动进行主从切换的,也就是说,如果主节点非常不争气的在凌晨3点挂了,那么运维同学就要马上起床,把从节点改成主节点,这样的操作是非常繁琐低效的.为此,Redis官方提供了一种解决方案:Redis Sentinel 简介 Redis Sentinel集群通常由3到5个节点组成,如果

  • Redis 哨兵集群的实现

    目录 1.Sentinel 哨兵 2.Redis 主从分离 一.配置Master 二.配置Slave 1.在配置文件中配置从服务 2.在服务启动后设置 3.总结 3.Sentinel 哨兵 1.配置端口 2.配置主服务器的ip 和端口 3.启动Sentinel 4.关闭Master 5.重连Master 4.Sentinel 总结 一.Sentinel的作用: 二.Sentinel的工作方式: 1.Sentinel 哨兵 Sentinel(哨兵)是Redis 的高可用性解决方案:由一个或多个Se

  • k8s部署redis cluster集群的实现

    Redis 介绍 Redis代表REmote DIctionary Server是一种开源的内存中数据存储,通常用作数据库,缓存或消息代理.它可以存储和操作高级数据类型,例如列表,地图,集合和排序集合. 由于Redis接受多种格式的密钥,因此可以在服务器上执行操作,从而减少了客户端的工作量. 它仅将磁盘用于持久性,而将数据完全保存在内存中. Redis是一种流行的数据存储解决方案,并被GitHub,Pinterest,Snapchat,Twitter,StackOverflow,Flickr等技

  • docker搭建redis哨兵集群并且整合springboot的实现

    目录 1.创建两个文件夹redis和sentinel文件夹用于存放docker-compose.yml文件 2.redis下的docker-compose.yml 3.sentinel下的docker-compose.yml文件以及sentinel.conf配置文件 4.spring boot整合redis哨兵 5.哨兵工作方式 6.Redis-Cluster集群 7.redis常见问题 1.创建两个文件夹redis和sentinel文件夹用于存放docker-compose.yml文件 2.r

  • Redis cluster集群的介绍

    1.前言 Redis集群模式主要有2种: 主从集群.分布式集群. 前者主要是为了高可用或是读写分离,后者为了更好的存储数据,负载均衡. redis集群提供了以下两个好处 1.将数据自动切分(split)到多个节点 2.当集群中的某一个节点故障时,redis还可以继续处理客户端的请求. 一个 redis 集群包含 16384 个哈希槽(hash slot),数据库中的每个数据都属于这16384个哈希槽中的一个.集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽.集群中

  • Redis Cluster集群动态扩容的实现

    目录 一.引言 二.Cluster集群增加操作 1.动态增加Master主服务器节点 2.动态增加Slave从服务器节点 三.Cluster集群删除操作 1.动态删除Slave从服务器节点 2.动态删除Master主服务器节点 四.总结 一.引言 上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cluster集群的状态,也可以使用Cluster Nodes 命令来详细

随机推荐