Redis的主从复制原理
程序员文章站
2024-02-29 21:25:52
...
Redis主从复制
Redis是什么
- Redis持久化保证了即便Redis服务重启也不会丢失数据,redis服务重启后会将磁盘上持久化的数据恢复到内存中,若redis服务器的磁盘损坏则可能导致数据丢失
- Redis读写速度特别快,但也会有读写压力特别大的时候,为了分担I/O过高,Redis支持主从复制,结构是一主多从或者级联结构;Redis主从复制可根据是否是全量分为全量同步和增量同步
Redis主从复制的特点
- 同一个master可以拥有多个slave
- master下的slave还可以接受统一架构中其他slave的连接与同步清酒,实现数据的级联复制,即master→slave→slave模式
- master以非阻塞的方式同步数据至slave,这将意味着master会继续处理client的读写请求
- slave端同步数据也可以修改为非阻塞的方式,当slave在执行新的同步时,它任可以用就得数据信息来提供查询
- redis的主从复制具有可扩展性,即多个slave专门提供只读查询与数据的冗余,master端专门提供写的操作,实现读写分离
- 通过配置禁用master数据持久化机制,将其数据持久化操作交给slave完成,避免在master中要有独立的进程来完成此操作
全量同步
- Redis全局复制一般发生在slave初始化阶段,这时slave需要将master上的数据都复制一份,操作如下
- 从服务器连接主服务器,发送SYNC命令
- 主服务器接收到SYNC命令后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令
- 主服务器BGSAVE执行完成后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令
- 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照
- 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令
- 从服务器完成对快照的载入,开始接受命令请求,并执行来自主服务器缓冲区的写命令
根据以上的步骤就完成了从服务器数据初始化的所有操作,从服务器此时可以接收来自用户的读请求
- 若master和slave之间的连接出现断开,slave可以自动重连到master,版本不同断连后同步的方式也不同
- 2.8之前:重连成功后,一次全量同步操作将被自动执行
- 2.8以后:重连成功后,进行部分同步操作
增量同步
- Redis增量复制是指slave初始化后开始正常工作时,主服务器发送的过程;增量复制的过程主要是主服务器每执行一个写命令就会从服务器发送相同的写命令,从服务器接收并执行收到的写命令
master持久化功能关闭时,将带来复制的安全性
- 当我们部署redis主从复制的时候,一般都会强烈建议把master的持久化开关打开,即使为了避免持久化带来的延迟影响,不把持久化开关打开,那么也该把master配置为不会自动启动,因为master异常刷新后重启非常危险,会导致slave中的数据被清空
- 假设我们有一个redis节点A,设置为master,并且关闭持久化功能,另外两个节点B和C是它的slave,并从A复制数据
- 如果A节点崩溃了导致所有的数据都丢失了,它会重启系统来重启进程,但是由于持久化功能被关闭,所以即使重启它的数据集也是空的
- 而B和C依然会通过replication机制从A复制数据,所以B和C会从A那里复制到一份空的数据集,并用这份空的数据集将自身的非空数据集替换掉,于是就相当于丢失所有数据了
- 即使使用一些工具,如sentinel来监控master-slave集群,也会发生上述情形,因为master可能崩溃后迅速恢复,速度太快而导致sentinel无法察觉一个failure的发生
Redis2.8之后主从复制的过程
- 在redis2.8前从redis每次同步都会从主redis中复制全部的数据,如果从redis是新创建的,则从主redis中复制全部的数据这是没有问题的,但是当从redis停止,再启动可能就只有少部分数据和主redis不同步,此时启动redis仍会从主redis复制全部数据,这样的性能肯定没有只复制那一小部分不同步的数据高
- 部分复制
- 从机连接主机后,会主动发起PSYNC(部分同步)命令,从机会提供master的runid(机器标识,随机生成的一个串)和offset是否有效,runid相当于主机身份验证码,用来验证从机上一次连接的主机,如果runid验证未通过,则进行全量同步,若通过则说明曾经同步过,根据offset同步部分数据
- 部分复制的工作原理
- 主服务器端为复制流维护一个内存缓冲区,主从服务器都维护一个复制偏移量和master runid,当连接断开时,从服务器会重新连接上主服务器,然后请求继续复制,假如主从服务器的两个master runid相同,并且指定的偏移量在内存缓冲区中还有效,复制就会从上次中断的点开始继续,如果其中一个条件不满足,就会进行完成全重新同步,因为主运行id不保存在磁盘中,如果从服务器重启了就只能进行完全同步了
- 无磁盘的复制
- 通常的一个同步需要在磁盘上创建一个RDB文件,然后再重新加载这个文件来进行与slave数据同步,由于磁盘的读写是非常慢的,这对于redis master是一个非常有压力的操作,在2.8.18尝试使用无磁盘的复制,在这个设置里,进程直接把RDB发送到slaves,而不需要使用磁盘来做中间的存储
- 主从切换
- 万一主机down了,redis提供了一个sentinel(哨兵),一次来实现主从切换的功能,类似与zookeeper
- 我们配置两个sentinel进程
vim sentinel.conf port 26379 sentinel monitor mymaster 127.0.0.1 6000 2 sentinel auth-pass mymaster 123456
vim sentinel.conf port 26479 sentinel monitor mymaster 127.0.0.1 6000 2 sentinel auth-pass mymaster 123456
- 启动sentine服务:
redis-server sentinel.conf --sentinel
上一篇: tf.nn.embedding_lookup函数的用法
下一篇: Redis主从复制原理