Redis主从复制 | |
什么是主从复制 | 主从复制,就是将主服务的数据复制到从服务器
需要注意的是数据的复制是单向的,只能是由主节点到从节点
默认每台redis的服务器的都是主节点,一个主节点有多个从节点,但一个从节点只能有一个主节点 |
主从复制的作用主要包括 | 1)数据冗余,就是将数据持久化
2)故障恢复 也是一种服务的冗余
3)负载均衡 主从复制基础上,配合读写分离,主提供写,从提供读
4)读写分离
5)高可用 主从复制是哨兵以及集群的基础
6) 容量瓶颈(单一台机器不够用的时候) |
Redis主从复制的步骤 | Dockfile build redis 通过docker命令分别运行redis容器(主从)
1.配从库不配主库 |
从节点开启主从复制,有3种方式 | 1)配置文件,在从服务器的配置文件中加入 Slaveof <masterip> <masterport>
2)启动命令 Redis-server启动命令后加入 Slaveof <masterip><masterport>
3)客户端命令 redis服务器启动后,可以通过客户端执行命令 Slaveof <masterip><masterport>
则该redis实例可以成为从节点
通过info replication 命令可以看到复制的一些参数信息 |
主从复制原理 | 主从复制过程大体可以分为3个阶段 1)主从建立连接阶段,即准备阶段(info replication)
2)数据同步阶段(ping 权限密码 同步数据(增量/全量))
3)命令传播阶段(主把写命令写到从)
详细: 1)保存主节点信息
2)主从建立连接(关于连接失败,在从节点上执行 info replication查看)
3)发送ping命令(检测主节点能否接收命令)
4)权限验证(与主节点相同的密码才可以登入)
5)同步数据(主节点把数据全量发送给从节点)
6)命令持续复制
注意: 主从在同步的过程中,会把原本的从节点上的数据清空 |
全量复制 | 初次复制或者其他无法进行部分复制的情况,会将主节点上的全部数据发送到从节点,会是一个重型的操作,当数据量较大时,会对主从节点以及网络造成很大的开销 |
部分复制 | 在主从复制的时候由于网络闪断等原因造成数据丢失,当从节点再次连上主节点后,如果条件允许,会补发丢失的数据给从节点 需要注意的是如果网络中断时间过长,会无法部分复制,会使用全量复制的 |
复制偏移量 | 参与复制的主从节点都会记录自身复制偏移量 主节点在处理完命令后,会做一个累加记录 可以通过info replication中的 Master_repl_offset Slave_repl_offset |
复制积压缓冲区 | 复制积压缓冲区是保存在主节点上的一个固定长度的队列,当从节点被创建的时候,不但会把命令发送给从节点,还会写入到复制缓冲区,作为写命令的备份,默认大小为1MB。 除了存储写命令,还存储了对应的复合偏移量,它保存的是主节点最近执行的写命令,时间较早的写命令会被挤出缓冲区。 (主节点在发送命令给到从节点的时候,还会写入到复制积压缓冲区,保存着最近写的命令+偏移量) |
Redis全量复制的过程如下 | 1)redis会发出一个同步命令
2)主机向从机发送runid和offset,如果是第一次,从服务器没有对应的offset,会是全量复制
3)从机会保存主机的的基本信息
4)主机收到全量复制的命令后,执行bgsave异步执行,在后台生成RDB快照文件,并使用缓冲区记录从现在开始执行的所有写命令
5)主机会发送RDB快照文件给从机
6)发送缓冲区数据
7)刷新旧的数据,会把从节点老的数据清除
8)从节点加载RDB快照文件 |
全量复制开销,主要有以下几项 | 1)Bgsave异步执行的时间
2)RDB快照文件网络传输的时间
3)从节点清空数据的时间
4)从节点加载RDB的时间 |
部分复制 | 当主机出现抖动的时候,可以将复制的损失降低到最低
1)如果网络抖动
2)主机还是会写复制缓冲区
3)从机还是会继续尝试连接主机
4)从机会把自己当前的runnid和偏移量传输给主机,并且执行同步命令
5)如果主机发现你的偏移量是在缓冲区范围内,就会执行continue命令 |
正常情况下redis是如何决定是全量复制还是部分复制 | 主要是根据offset和缓冲区大小决定能否执行部分复制
如果offset偏移量之后的数据,仍然在复制积压缓冲区里,则执行部分复制,反之则执行全量复制。 |
缓冲区大小调节 | Repl-backlog-size设定 例如 如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见,可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。 |
服务器运行ID(runid)
| 每个redis节点,不论主从,在启动的时候都会自动随机生成一个唯一的ID.
节点的唯一标识
通过info server命令,可以查看节点的runnid |
主从复制进阶常见问题解决 虽然读写有优势,能够让读这部分分配给各个从机,如果不够,可以直接加从服务器,但是也会出现以下问题 | |
1.数据延迟
| 可以结合swoole编写外部监控程序监听主从节点的复制偏移量,当延迟较大时就会触发报警。(info replication offset)
同时从节点的slave-server-stale-data参数也与此有关,控制着当从库同主机失去连接或者复制正在进行,从库有两种运行方式: 1)slave-server-stale-data=yes,从库会继续响应客户端的请求 2)slave-server-stale-data=no,除去info和slavof命令之外的任何请求都只会返回一个一个错误 主机同步数据正在进行
|
2.异步复制导致数据丢失 | 解决办法: (请记住只能降低到可控范围,没办法做到100%不会丢失) Min-slaves-to-write 1 最少有多少台机器才能写入 Min-slaves-max-lag 10
一旦延迟超时,主库就会拒绝写的请求,避免造成更大的损失
就是说一旦所有的从库,数据复制和同步的延迟都超过了10秒钟,那么这个时候,主库就不会再接收任何请求。 有了min-slaves-max-lag这个配置,就是说一旦复制延时过长,或者损失的数据太多,主库就会拒绝写的请求,这样可以降低数据丢失的风险。 |
3、主从配置不一致 |
|
4、规避全量复制 |
|
5、规避复制风暴 |
|
常见配置参数 | |
slave实例需要配置该项,指向master的(ip, port)。 | Slaveof <masterip><masterport> |
如果master实例启用了密码保护,则该配置项需填master的启动密码;若master未启用密码,该配置项需要注释掉 | Masterauth<master-password> |
指定 slave 与 master 连接中断时的动作。默认为yes,表明主从中断时,slave会否继续应答来自client的请求,但这些数据可能已经过期(因为连接中断导致无法从 master 同步)。 若配置为no,则slave除正常应答"INFO"和"SLAVEOF"命令外,其余来自客户端的请求命令均会得到" SYNC with master in progress "的应答,直到该 slave 与 master 的连接重建成功或该 slave 被提升为 master 。 | Slave-server-stale-data |
指定slave是否只读,默认为yes。若配置为no,这表示slave是可写的,但写的内容在主从同步完成后会被删掉。 | Slave-read-only |
指定向slave同步数据时,是否禁用 socket 的 NO_DELAY 选项。若配置为yes,则禁用 NO_DELAY ,则TCP协议栈会合并小包统一发送,这样可以减少主从节点 间的包数量并节省带宽,但会增加数据同步到slave的时间。 若配置为no,表明启用 NO_DELAY ,则TCP协议栈不会延迟小包的发送时机,这样数据同步的延时会减少,但需要更大的带宽。通常情况下,应该配置为no以降 低同步延时,但在主从节点间网络负载已经很高的情况下,可以配置为yes。 | Repl-diable-tcp-nodelay |
指定 slave 的优先级。在不只1个 slave 存在的部署环境下,当 master 宕机时, Redis Sentinel 会将priority值最小的slave提升为master。需要注意的是,若 该配置项为0,则对应的slave永远不会被 Redis Sentinel 自动提升为 master 。
| Slave-prioriity |