Redis集群之主从复制

本文来说下Redis集群之主从复制


概述

跟Kafka、RocketMQ、MySQL、ZooKeeper一样,Redis支持集群的架构,集群的节点有主节点和从节点之分。主节点叫master,从节点叫slave。slave会通过复制的技术,自动同步master的数据。

Redis主从复制解决了数据备份和一部分性能的问题。但是没有解决高可用的问题,在一主一从或者一主多从的情况下,如果主服务器挂了,对外提供的服务就不可用了,需要手动把从服务器切换成主服务器,然后再把剩余节点设置为它的从节点,这个比较费时,还会造成一定时间的服务不可用。


主从复制

当其中一台服务器更新之后,服务器会自动的将这台更新的数据同步到另外一台服务器上。通过持久化的功能,redis可以保证就算是服务宕机重启了,也只有少量的数据会丢失。但是在真实的使用场景当中,如果真的只有一台服务器,并且恰好宕机了,那么就会导致整个服务都不可用,因此redis提供了集群的方式来部署,可以避免这种问题。

在这里插入图片描述

在主从复制这种集群部署模式中,我们会将数据库分为两类,第一种称为主数据库(master),另一种称为从数据库(slave)。

主数据库会负责我们整个系统中的读写操作,从数据库会负责我们整个数据库中的读操作。

其中在职场开发中的真实情况是,我们会让主数据库只负责写操作,让从数据库只负责读操作,就是为了读写分离,减轻服务器的压力。

但是我在实际开发中会遇到一种情况,该数据是个热点数据,我们知道,数据同步一定是会耗时的,那么当一个热点数据进入master中,而slave没有来得及更新,再去读这个数据就会造成数据不一致现象,所以当时我的方案就是直接去读master节点,这个逻辑同样适用于mysql主从中出现的问题。


主从同步原理

主从同步原理

  • 当一个从数据库启动时,它会向主数据库发送一个SYNC命令
  • master收到后,在后台保存快照,也就是我们说的RDB持久化,当然保存快照是需要消耗时间的,并且redis是单线程的(redis后面也支持了多线程,这里我们先不讲),在保存快照期间redis收到的命令会缓存起来,快照完成后会将缓存的命令以及快照一起打包发给slave节点,从而保证主从数据库的一致性。
  • 从数据库接受到快照以及缓存的命令后会将这部分数据写入到硬盘上的临时文件当中,写入完成后会用这份文件去替换掉RDB快照文件,当然,这个操作是不会阻塞的,可以继续接收命令执行,具体原因其实就是fork了一个子进程,用子进程去完成了这些功能。

因为不会阻塞,所以,这部分初始化完成后,当主数据库执行了改变数据的命令后,会异步的给slave,这也就是我们说的复制同步阶段,这个阶段会贯穿在整个主从同步的过程中,直到主从同步结束后,复制同步才会终止。


上文提到的数据不一致是怎么回事

是因为redis采用了乐观复制的策略:

容忍一定时间内主从数据库的数据是不一致的,但是会保证最终的结果一致。

所以当主从复制发生时,正常情况下的命令都会在主数据库完成,然后直接反回给客户端,这样我们的性能就不会受到影响了,因为这里是主数据库先完成命令,那么就会产生其他问题。

举个例子,假如现在有1个master,6个slave,现在只有两个slave完成了同步,master写了新命令,在master准备将此命令传输给其他slave时,此刻其他的slave断电了,那么就会造成数据不一致的现象发生。

所以redis针对这种情况作了两个配置

min-slaves-to-write    2  
 (只有2个及以上的从数据库连接到了主数据库时,master库才是可写的)
min-slaves-max-lag   10 
 (10秒slave没有和master进行交互就认为丢失链接)

无硬盘复制

我们刚刚说了主从之间是通过RDB快照来交互的,虽然看来逻辑很简单,但是还是会存在一些问题:

  • master禁用了RDB快照时,发生了主从同步(复制初始化)操作,也会生成RDB快照,但是之后如果master发成了重启,就会用RDB快照去恢复数据,这份数据可能已经很久了,中间就会丢失数据
  • 在这种一主多从的结构中,master每次和slave同步数据都要进行一次快照,从而在硬盘中生成RDB文件,会影响性能

为了解决这种问题,redis在后续的更新中也加入了无硬盘复制功能,也就是说直接通过网络发送给slave,避免了和硬盘交互,但是也是有io消耗的。


增量复制

为什么会有增量复制?

刚刚我们说了复制的原理,但是他的缺点是很明显的,就是在断开主从链接后,即使你只发生了一条数据变化,也需要将所有的数据通过SYNC命令用RDB将所有的数据同步给slave,但是其实并不需要同步所有的数据,只需要将改变的这小部分数据同步给slave就好了

所以为了解决这个问题,redis就有了增量复制。

这个原理其实是很简单的,学过kafka 的小伙伴应该知道,kafka消费是通过偏移量来计算的,redis的增量复制也是如此。

master会记下每个slave的id,在复制期间,如果有新消息,会将新消息(其实是新的命令,当然只包括让数据放生变动的命令,如 set 这种 )存放在一个固定大小的循环队列中,这个大小是可以配置的,当然这时候发送的就是PSYNC命令了,然后master会在复制完成后将这部分数据发送给slave,这样就在很大程度上保证了数据一致性。


本文小结

本文详细介绍了Redis集群主从复制相关的知识与原理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值