Redis持久化与集群

文章详细介绍了Redis的持久化机制,包括RDB快照和AOF日志,以及它们的优缺点和重写策略。接着讨论了Redis主从复制的工作原理和数据部分复制功能。最后,深入探讨了RedisCluster集群的搭建、与哨兵模式的比较、集群原理,如槽位定位算法、节点通信机制和故障处理策略,强调了集群至少需要3个master节点的原因。
摘要由CSDN通过智能技术生成

1.持久化

1.1 RDB快照

  默认情况下, Redis 将内存数据库快照保存在名为 dump.rdb 的二进制文件中。
  让 Redis 满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:
# save 60 1000 //关闭RDB只需要将所有的save保存策略注释掉即可
  也可以手动执行生成RDB快照命令,进入redis客户端执行命令save或bgsave生成dump.rdb文件, 每次执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件

bgsave写时复制(COW)机制

  Redis 借助操作系统提供的写时复制技术(Copy-On-Write, COW),在生成快照的同时,依然可以正常处理写命令。bgsave 子进程是由主线程 fork 生成的,可以共享主线程所有内存数据。 bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。此时,如果主线程对这些数据是读操作,主线程和 bgsave 子进程间相互不影响。但是,如果主线程要修改一块数据,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

1.2 AOF

  如果 Redis 因为某些原因而故障停机, 服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本后, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件appendonly.aof中(先写入操作系统缓存os cache,每隔一段时间 fsync到磁盘)。

通过修改配置文件打开 AOF 功能:

# appendonly yes

  每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件末尾。 这样的话, 当 Redis 重新启动时,程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。

配置 Redis 多久将数据 fsync 到磁盘一次:

appendfsync everysec:每秒 fsync 一次,足够快,并且在故障时只会丢失 1 秒钟的数据。

AOF重写

AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件。
控制AOF自动重写频率:

# auto‐aof‐rewrite‐min‐size 64mb //aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大 
# auto‐aof‐rewrite‐percentage 100 //aof文件自上一次重写后文件大小增长了100%则再次触发重写

AOF重写redis会fork出一个子进程去做(与bgsave命令类似),不会对redis正常命令处理有太多影响

RDB 和 AOF对比

命令RDBAOF
启动优先级
体积
恢复速度
数据安全性容易丢数据根据策略决定

生产环境可以都启用,redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof 一般来说数据更全一点

1.3 混合持久化

Redis 4.0后开启混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。
混合持久化AOF文件结构

在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,因此重启效率大幅得到提升。

2.redis主从

2.1 工作原理

在这里插入图片描述
1.每个slave,不管这个slave是否是第一次连接上Master,它都会发送一个PSYNC 命令给master请求复制数据;
2.1. master收到PSYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件
2.2 持久化期间,master会继续接收客户端请求,把这些可能修改数据集的请求缓存在内存中;
3. 当持久化完毕后,master会把这份rdb文件数据集发送给slave;
4. slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中;
5. master再将之前缓存在内存中的命令发送给slave;

  当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。

数据部分复制

(部分复制,断点续传)
  当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后只进行部分数据复制(断点续传)。
  master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,master和它所有的 slave都维护了复制的数据下标offset和master的进程id,因此,当网络连接断开后,slave会请求master 继续进行未完成的复制,从所记录的数据下标开始。如果master进程id变化了,或者从节点数据下标 offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。

3.redis cluster集群

3.1 集群搭建

redis集群需要至少三个master节点,并且每个master再搭建一个slave节 点,总共6个redis节点,用三台机器部署6个redis实例,每台机器一主一从。

3.2 与哨兵模式比较

  在redis3.0以前要实现集群一般是借助哨兵sentinel工具来监控master节点的状态,如果master节点异常,则会做主从切换,将某一台slave作为master,哨兵的配置略微复杂,并且性能和高可用性等各方面表现一般,特别是在主从切换的瞬间存在访问瞬断的情况,而且哨兵模式只有一个主节点对外提供服务,没法支持很高的并发,且单个主节点内存也不宜设置得过大(<10G),否则会导致持久化文件过大,影响数据恢复或主从同步的效率。
  redis cluster是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群不需要sentinel哨兵也能完成节点移除和故障转移的功能:需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点),redis集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。

3.3 集群原理

  Redis Cluster 将所有数据划分为 16384 个 slots(槽位),每个节点负责其中一部分槽位。槽位的信息存储于每个节点中。
  当 Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息并将其缓存在客户端本地。这样当客户端要查找某个 key 时,可以直接定位到目标节点。同时因为槽位的信息可能会存在客户端与服务器不一致的情况,还需要纠正机制来实现槽位信息的校验调整。

3.3.1 槽位定位算法

  Cluster 默认会对 key 值使用 crc16 算法进行 hash 得到一个整数值,然后用这个整数值对 16384 进行取模来得到具体槽位。这个分槽的方法就是分片算法中的查表法
HASH_SLOT = CRC16(key) mod 16384

为什么槽的范围是 0 ~16383?
  Redis 集群在握手成功后,节点间会定期发送 ping/pong 消息交换数据信息。集群中节点数量越多,消息体内容越大,比如说 10 个节点的状态信息约 1kb。同时 redis 集群内节点,每秒都在发 ping 消息。在这种情况下,一个总节点数为 200 的 Redis 集群,默认情况下,这时 ping/pong 消息占用带宽达到25M,这还只是槽的范围是 0 ~16383 的情况。如果槽位设计为 65536,光发送心跳信息的消息头可达 8k,发送的心跳包过于庞大,非常浪费带宽。
  其次 redis 的集群主节点越多,心跳包的消息体内携带的数据越多。如果节点过 1000 个,也会导致网络拥堵。因此 redis 作者,不建议 redis cluster 节点数量超过 1000 个。
  对于节点数在 1000 以内的 redis cluster 集群,16384 个槽位够用了,可以以确保每个 master 有足够的插槽,没有必要拓展到 65536 个。所以 Redis 作者决定取 16384 个槽,作为一个设计权衡。

跳转重定位

在这里插入图片描述
  当客户端向一个错误的节点发出了指令,该节点会发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去连这个节点去获取数据。客户端收到指 令后除了跳转到正确的节点去操作,还会同步更新纠正本地的槽位映射表缓存,后续所有 key 将使用新的槽位映射表。

3.3.2 集群间通信机制

维护集群的元数据(集群节点信息,主从角色,节点数量,各节点共享的数据等)有两种方式:集中式和gossip。

集中式
优点:元数据的更新和读取,时效性非常好,一旦元数据出现变更立即就会更新到集中式的存储中,其他节点读取的时候立即就可以立即感知到;
缺点:所有的元数据的更新压力全部集中在一个点,可能导致元数据的存储压力;
很多中间件都会借助zookeeper集中式存储元数据。

gossip
gossip协议包含多种消息,包括ping,pong,meet,fail等等
在这里插入图片描述
meet:某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通信;
ping:每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过 ping交换元数据(类似自己感知到的集群节点增加和移除,hash slot信息等);
pong: 对ping和meet消息的返回,包含自己的状态和其他信息,也可以用于信息广播和更新;
fail: 某个节点判断另一个节点fail之后,就发送fail给其他节点,通知其他节点,指定的节点宕机了。

优点:元数据的更新比较分散,不是集中在一个地方,更新请求会陆陆续续,打到所有节点上去更新,有一定的延时,降低了压力;
缺点:元数据更新有延时可能导致集群的一些操作会有一些滞后。

gossip通信的+10000端口

  每个节点都有一个专门用于节点间gossip通信的端口,就是自己提供服务的端口号+10000,比如7001,那么用于节点间通信的就是17001端口。 每个节点每隔一段时间都会往另外几个节点发送ping消息,同时其他节点接收到ping消息之后返回pong消息

3.3.3 网络抖动

  为解决网络抖动,Redis Cluster 提供了一种选项cluster­-node-­timeout,表示当某个节点持续 timeout 的时间失联时,才可以认定该节点出现故障,需要进行主从切换。如果没有这个选项,网络抖动会导致主从频繁切换 (数据的重新复制)。

3.3.4 集群选举原理

  当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master 可能会有多个slave,存在多个slave竞争成为master节点的过程, 其过程如下:

  1. slave发现自己的master变为FAIL
  2. 将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST 信息
  3. 其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个 epoch只发送一次ack
  4. 尝试failover的slave收集master返回的FAILOVER_AUTH_ACK
  5. slave收到超过半数master的ack后变成新Master(如果只有两个,当其中一个挂了,只剩一个主节点是不能选举成功的)
  6. slave广播Pong消息通知其他集群节点。

  从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟,确保我们等待 FAIL状态在集群中传播,slave如果立即尝试选举,其它masters或许尚未意识到FAIL状态,可能会拒绝投票。

  • 延迟计算公式:
    DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms
  • SLAVE_RANK表示此slave已经从master复制数据的总量的rank。Rank越小代表已复制的数据越新。这种方式下,持有最新数据的slave将会首先发起选举(理论上)

3.3.5 集群脑裂数据丢失问题

  redis集群没有过半机制会有脑裂问题,网络分区导致脑裂后多个主节点对外提供写服务,一旦网络分区恢复,会将其中一个主节点变为从节点,这时会有大量数据丢失。
  min‐replicas‐to‐write 1 //写数据成功最少同步的slave数量,这个数量可以模仿大于半数机制配置,比如集群总共三个节点可以配置1,加上leader就是2,超过了半数。
  但是这个配置在一定程度上会影响集群的可用性,比如slave挂掉导致数量少于1个,这个集群就算leader正常也不能提供服务了,需要具体场景权衡选择。

3.3.6 Redis集群为什么至少需要三个master节点,并且推荐节点数为奇数?

  新master的选举需要大于半数的集群master节点同意才能选举成功,如果只有两个master节点,当其中一个挂了,达不到选举新master的条件。
  奇数个master节点可以在满足选举该条件的基础上节省一个节点,比如三个master节点和四个master节点的集群相比,大家如果都挂了一个master节点都能选举新master节点,如果都挂了两个master节点都没法选举新master节点了,所以奇数的master节点更多的是从节省机器资源角度出发说的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

paopaodog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值