Redis 进阶(四)—— 主从复制(二)

3.8 数据同步

redis 中通过 psync 命令,完成数据同步,由redis 服务器在建好同步关系后,自动执行。

bash 复制代码
PSYNC replicationid offset

从节点执行 psync 命令,从主节点处获取数据。

同步按数据多少又分为 全量复制 和 部分复制

3.8.1 replicationid & offset

replicationid 是①主节点启动时生成, ②从节点变为主节点时也会生成。

同一个主节点,每次启动生成的 id 都不同。

主从节点建立关系后,从节点从主节点处获得 replicationid

这里的 master_replid 就是 replicationid。有主从关系的节点的这串字符是一样的。

master_replid2 一般用不上。假若有 主节点 甲 和 从节点 乙。甲乙间通信出现抖动,乙 认为 甲 挂了,乙自己变为主节点了(生成了自己的 replid),此时 replid2 记录的就是 甲 的 replid,后续网络恢复,乙可以根据 replid2 回到 甲的怀抱。、

offset 即偏移量。

主从节点都会维护 偏移量(整数)。

主节点偏移量,表示当前的数据量(主节点会收到很多修改操作命令,每个命令都要占据几个字节,主节点会将这些命令的字节数累加)

从节点偏移量:表示从节点数据同步到了哪里。

主从偏移量一致,说明从节点复制完了。

从节点每秒钟要上报自己的偏移量给主节点。

replicationid 和 offset 共同描述了一个 "数据集合",如果两台机器上的 replicationid 和 offset 都相同,说明这俩个 redis 机器上存的数据一样。

3.8.2 全量复制 & 部分复制

复制多少主要看 offset。 offset 为 -1 时,就是全量数据;如果是具体正整数,则从当前偏移量位置进行获取。

从发送 psync 同步请求,master 有三种返回结果。

  1. fullresync 全量数据同步
  2. contineu 增量数据同步
  3. err 较老版本的 redis 服务器不支持 psync,使用 sync 代替。

全量复制时机:① 主从首次数据同步;② 主节点不方便部分复制时。

部分复制时机:从节点之前已复制过,但因网络抖动或从节点重启,要重新从主节点同步数据,此时看看能不能只同步一部分。

3.8.3 全量复制流程

  1. 从节发送 psync 命令 给主节点,首次复制,没有主节点 replid 和 复制偏移量,所有发送 `psync ? -1``
  2. 主节点解析命令知道是全量复制,回复 +FULLRESYNC
  3. 从节点接收主节点的信息并保存
  4. 主节点执行 bgsave 进行 rdb 文件的持久化
  5. 主节点将 rdb 文件发给 从节点,从节点将 rdb 文件保存到本地硬盘
  6. 从节点清空旧数据
  7. 从节点加载 rdb 文件
  8. 主节点将生成 rbd 文件时收到的命令写入缓冲区,从节点保存完 rdb 文件后,主节点将缓冲区内数据发给从节点,从节点执行这些命令,并保持数据一致性
  9. 从节点如何开启了 aof 持久化,就进行 bgrewrite 操作,得到新的 aof 文件

全量复制,还支持无硬盘模式,即 主节点生成的 rdb 二进制数据,不再保存到 rdb 文件中发给从节点,而是直接通过网络传输给从节点(省下一系列硬盘读写操作);从节点也不再先将rdb 数据写入硬盘,然后从硬盘加载,而是直接加载收到的数据。

虽然有无硬盘模式,但是全量复制操作依然很重,且网络传输是没法省的(一般情况:内存速度 > 硬盘 > 网络),相比于网络传输,硬盘操作算是小的了。

3.8.4 replicationid VS runid

网上一些资料提到 runid 是用来进行复制的,但是不太对。

redis 服务器上这两个 id 都有,虽然这两个的长度相同,格式相似。但 runid 是每个节点都不同,而有主从关系的节点的 replid 是相同的。

前面的命令(摘自官方文档)

bash 复制代码
PSYNC replicationid offset

也明确表明用 replid

runid 用于标识一次 redis 的 "运行",主要用在 redis 哨兵功能的实现,和主从复制没什么关系。

3.8.5 部分复制流程

全量复制开销大,从节点中已有主节点中大部分数据时,就不需要进行全量复制了,应进行部分复制。

  1. 主从节点间网络中断超过 timeout 时间,主节点认为从节点挂了终止复制连接
  2. 断连期间,主节点正常响应命令,但这些命令因网络中断无法发给从节点,命令就会积攒在复制积压缓冲区中
  3. 主从网络恢复后,从节点重新连上主节点
  4. 从节点将之前保存的 replicationid 和 offset 作为 psync 参数发给主节点,请求部分复制
  5. 主节点收到请求后,进行必要的验证,然后根据 offset 在积压缓冲区中找合适的数据,并返回 +CONTINUE 给从节点
  6. 主节点将从节点需要的数据发给从节点,完成一致性

如果从节点发来的 replicationid 和主节点不一致,说明这个从节点之前在别的主节点手下,就要进行全量复制。

如果相同,说明是自己的,然后看 offset 判定从节点落下的数据,如果缓冲区保存的数据最小 offset 都比从节点的大,那就没办法部分复制了,就要进行全量复制。如果 offset 在缓冲区范围内,就从 offset 开始进行部分复制。

下面箭头指的框,就是 复制积压缓冲区 的设置。

这个缓冲区就是一个内存中的队列,会记录最近一段时间修改的数据,但是总量有限,随时间推移会将之前旧的数据删掉。

bash 复制代码
repl_backlog_active:1 // 开启复制缓冲区
repl_backlog_size:1048576 // 缓冲区最⼤⻓度
repl_backlog_first_byte_offset:1 // 起始偏移量,计算当前缓冲区可⽤范围
repl_backlog_histlen:4147 // 已保存数据的有效⻓度

3.8.6 实时复制

当前主从节点数据已经一致,但后续主节点不断收到修改数据的请求,主节点的数据就会改变,从节点数据也要随之改变。

主从节点之间会建立 TCP 长连接,主节点将自己收到的修改数据的请求,通过该连接发送给从节点,从节点根据这些请求修改内存中的数据。

主节点通过 TCP 发送收到的请求,正常来说,延时较短,但若是多级从节点的树形结构,有很多层,延时就会上升。

实时复制时要求连接处于可用状态,因而引入了心跳包机制。

主节点:默认,每 10 s 给从节点发送一个 ping 命令,从节点收到就返回 pong。

从节点:默认,每 1s 给主节点发起一个特定请求,上报当前自身的复制进度(offset)

3.8.7 主从连接的情况

有两种:

① 从节点主动断开,通过 slaveof no one 命令,这时从节点自动晋升主节点

② 主节点挂了,这时从节点不会晋升主节点,需人工干预,恢复主节点。

但是人工效率不高,还成本高。因而就有了 Redis 哨兵,自动对挂的主节点进行替换。(后面文章会讲)

3.8.8 关停主节点后,主节点无法再启动

之前,修改配置文件时,没有修改工作目录,导致三个 redis-server 共用同一个 aof 文件(虽然,有主从关系,但数据还是有概率不一致的)。

从节点是通过 redis-server 启动的,是 root 用户启动 reids 服务器,生成的 aof 文件也就是 root 用户的文件。

而主节点通过 service redis-server start 命令启动,是通过 redis 这样的用户,来启动的,文件属于 redis 用户。(root 启动 redis 权限太高,一旦redis 被 黑客攻破,后果比较严重)

从上面可以看到 -r--r ,即 root 用户之外的只能读,而redis-server 需要按 可读可写的方式打开 aof 文件。因此,启动失败。

解决方案:将三个 redis 服务器的工作目录区分开(修改配置文件这的 dir 选项)

  1. 关掉之前的redis 服务器

  2. 删除之前工作目录下的 aof 文件,或通过 chown (change own)命令修改 aof 文件所属用户

  3. 给从节点创建新目录,更改从节点配置文件中的工作目录。

  1. 启动 redis

    观察到 aof 文件位置发生变化
相关推荐
预立科技1 天前
Redis 中 Lua 与 Pipeline 的相同点,区别,使用场景
redis·pipeline·lua
曲幽1 天前
FastAPI多进程部署:定时任务重复执行?手把手教你用锁搞定
redis·python·fastapi·web·lock·works
wWYy.1 天前
详解redis(15):缓存雪崩
数据库·redis·缓存
这周也會开心1 天前
Redis相关知识点
数据库·redis·缓存
Anastasiozzzz1 天前
Redis的键过期是如何删除的?【面试高频】
java·数据库·redis·缓存·面试
thulium_1 天前
Redis Cluster + Docker + --net=host在 WSL2 下是一个“看起来能跑,实际上必失败”的组合
redis·docker
打工的小王1 天前
Redis(二)数据类型
数据库·redis·缓存
笨蛋不要掉眼泪1 天前
Redis核心数据类型与命令
数据库·redis·缓存
小唐同学爱学习1 天前
短链接修改之写锁
spring boot·redis·后端·mysql
zhglhy1 天前
Redis Cluster 的数据分片机制
数据库·redis·缓存