redis-14-主从复制与读写分离
主从复制 + 读写分离
先回顾上一章我们学习的单点服务。
redis 单节点部署
优点:
- 成本低(服务器少)
- 部署简单(就一个单节点)
- 性能高(单机不需要同步数据,天然数据一致性)
缺点
- 单点故障(可靠性很差)
- CPU 处理能力受限(Redis 是单线程的)
主从复制
图上 3 个客户端都是读写主节点。假设,当流量小的时候,我们这个主节点完全可以满足业务需求,但是由于业务扩大,流量增加,redis 压力增大,其主要压力都是读,写的压力不大,所以一个节点写,问题也不大,扩展从节点就可以应对。
优点:
职责分明,读和写各司其职
扩展性好,加机器就可以。
故障恢复
如果上面的主节点宕机,可以手动把上面的一个从节点升级成主节点(后面会介绍哨兵,解决 手动切换的问题)
缺点
- 数据冗余,每个从节点都会有相同容量的数据。(后面讲集群分片,解决这个问题)
- 数据压力大,现在每个从节点都是全量复制主节点数据。如果 1 个主节点,过多的从节点也会造成数据同步压力。
- 我们单独看,发现 Master 是单点,如果宕机,就不能提供写数据能力了。(后面讲集群分片,解决这个问题)
搭建环境 1 主 2 从
使用 docker-compose.yml
1 | version: '3.1' |
进入主节点
1 | docker exec -it redis-master /bin/bash |
role:master 主节点
2 个从节点,分别是 172.21.0.2 和 172.31.0.3
在主节点写数据
在从节点读/写数据
主从复制原理
1 | slaveof 192.168.x.x 6379(端口) |
在主/从节点上输入
1 | info replication |
主节点
Slave1 的 IP 是 172.31.0.3,state 是在线(online),从节点读取命令的 offset(偏移量)是 42,lag 延时 1 秒。
主节点所有的命令转成字节,然后放到队列里,写入多少,最终记录的值就是 offset 得值。
master_repl_offset:42 主节点已写入的命令偏移量。 由此可见,主节点写入的命令偏移量(42)和从节点读入的命令偏移量(42)相等,说明主从节点数据是一致的。
master_replid:d224eca130a7204b9132396a4bca89c7132b828d
master_replid 是每次重启 redis 产生一个 40 位的 ID。主要用于主从复制.识别增量的一个标识。他是 replicationID。
master_replid2:0000000000000000000000000000000000000000
master_replid2 是主从节点发生改变之后,主节点宕机了,那么新的 replicationID 会放到 master_replid 中,原来的 replicationID 会放到这里。(后面介绍哨兵的时候,可以用到)
全量复制
- 节点初始化
- 扩容从节点
- 主节点故障,马上选一个新的主节点,run_id 会发生变化。执行 info server ,会看到 run_id:80f0d8b28678fc2e159f40a73537e30c2101b489
second_repl_offset:-1 为了主节点切换后或故障重启后,避免每次都要全量复制。
以下是缓冲区的配置
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2534
从节点
master_last_io_seconds_ago:6 从库与主库同步数据时间 6 秒前
master_sync_in_progress 0-未同步,1-已同步
slave_read_repl_offset:56 从节点复制的偏移量 56
master_repl_offset:56 主节点写入的偏移量 56 ,说明数据是一致的
slave_priority:100 从节点重新选举,成为主节点成功的几率,在所有子节点中,谁的这个数值越大,谁当上子节点的概率越高。
slave_read_only: 从节点只读模式 1-开启,0-未开启
connected_slaves:0,链接到从节点的信息,我们是从节点,也可以去链接从节点
全量复制
增量复制
主服务器有写操作,同步到从服务器的过程。复制的过程:主服务器执行一个命令就会给从服务器发送相同的命令,从服务器接收并执行收到的命令。主从服务器每 10 秒发送心跳(PING 命令)
主从的复制异步
主从复制,主节点是非阻塞的,主节点复制同步过程中,也可以处理外界的请求访问。
过期 Key
子节点不会让 Key 过期,而是等待主节点让 Key 过期,当主节点的 Key 过期的时候,主节点汇合成一个 DEL 命令,并传到所有的子节点上。
加速复制
默认情况,主节点接收 Sync 命令后执行 BgSave 后,先保存数据到磁盘上,如果磁盘性能差,那么这个写磁盘操作消耗性能较大,可以修改配置,不写入磁盘直接生成 RDB 快照给从节点,但是这里有一定风险,因为数据没有落到磁盘上,数据一旦丢失,无法追回。
1 | repl-diskless-sync yes |
主从数据一致性问题
由于网络延迟,数据复制等因素
主多从少
网络高峰期,可以等高风期过去后,进行增量复制(部分重同步),如果想要立即同步,在从节点输入
1 | 第一种方式 |
主少从多
全量复制,这种情况,比较少, 是由于从服务器开启了写模式,这样,让主服务器开启同步,每次主服务器全量同步从服务器的数据。这种模式不建议使用。
数据延迟
主从节点的复制偏移量,延迟较大的时候应该报警(报警程序)或通知客户端,切换主从节点或其他节点。
修改配置文件
1
slave-serve-stale-data no
除 info 和 slaveof 命令外的任何请求都会返回一个错误”sync with matster in progress” , 数据在同步,同步后再处理请求。
脏数据
产生原因:
- Redis 删除数据机制(主动、惰性、定时删除)。惰性,就是目前一个 key 已经过期了,不会立即删除它,要等到有人访问它才会判断是否过期,才会删除它。这样,一个过期的 key,没有被访问,就会一直放到内存中,那么就有了定时删除。主动删除,当前存储容量已经触发了当前的内存容量,然后进行主动删除。这是这些机制的原因,可能导致了 redis 的脏数据的问题。
- 开启子节点可写。
解决脏数据问题:
- 忽略。查询数据情况,可以忽略。如果写数据,那么要准确的。(比如下订单场景)
- 强制读取主节点,从节点间接变为备份服务器
- 从节点只读,规避从节点写入脏数据
- Redis 数据读取前,检查键过期时间来决定是否返回数据。(3.2 版本以后,已解决过期问题)
数据安全性
关闭主节点持久化提升性能,同时带来复制的安全性问题。当主节点没有把数据写到磁盘上,此时,突然主节点停电了,重新启动后,主节点的数据也就都没有了,但是这个时候,主节点的 run_id 变了,那么从节点发现 run_id 变了,开始同步主节点的数据,但是主节点数据是空的,那么之前的从节点也就同步了空的数据,导致从节点数据为空。(建议不要开启这个提升性能的功能)
性能优化
如何规避全量复制
第一次全量 复制解决方案:低峰时段挂载从节点。(凌晨 3 点)
选举从节点为主节点(哨兵机制或者我们知道哪个从节点是全量的数据,认为让那个全量的从节点变成主节点)
增大复制缓冲区
如何避免复制风暴
复制风暴:多个从节点同时发起复制。
单主节点复制风暴:主节点重启,多从节点全量复制。解决方案:选取从节点为主节点、树状复制结构(原来 1 个从节点下面挂 8 个从节点,我们可以按二叉树的形式去挂载或者 2 个分支,每个节点挂 4 个)。
单机多主复制风暴:一台机器,多个主节点(树状复制架构)。解决方案:把主节点分散到多台主机上。
如何学以致用,在哪些场景中应用Redis
《Go语言+Redis实战课》


添加微信 | 公众号更多内容 |
---|---|
![]() |
![]() |