redis主从详解

  • 主从详解
    • 主从配置
    • 拓扑
    • 原理
    • 数据同步
      • 概念
      • 复制偏移量
      • 复制积压缓冲区
      • 主节点运行ID
      • Psync命令
    • 全量复制流程
    • 部分复制流程
    • 心跳
    • 缓冲大小调节
  • 读写分离

内容来源为六星教育,这里仅作为学习笔记

主从详解

主从配置

参与复制的redis实例划分为主节点(master)和从节点(slave)。默认情况下,redis都是主节点。每个从节点只能有一个主节点,二主节点可以同时具有多个从节点。复制的数据流是单向的,只能有主节点复制到从节点。
redis对于主从复制有三种方式

在配置文件中加入 slaveof {masterHost} {masterPort} 随redis启动生效
在redis-server启动命令后加入 --slaveof {masterHost} {masterPort} 生效
直接使用命令: slaveof {masterHost} {masterPort}

slaveof 命令在使用的时候,可以运行期动态配置,也可以提前写入到配置文件中。
别名:slaveof 的别名 REPLICATION https://www.oschina.net/news/99797/redis-master-slave-terminology

修改配置的方式:
配置从节点的redis.conf

slaveof 192.160.1.150 6379
# replicaof <masterip> <masterport>
# masterauth <master-password>



在成功建立主从连接之后我们可以通过 info replication 命令查看复制相关状态

  1. 主节点 192.160.1.160 6379 复制状态信息

    127.0.0.1:6379> info replication
    # Replication
    role:master
    connected_slaves:1
    slave0:ip=192.160.1.140,port=6379,state=online,offset=1752,lag=1
    ...
    
  2. 从节点 192.160.1.140 6379 复制状态信息
    127.0.0.1:6379> info replication
    # Replication
    role:slave
    master_host:192.160.1.150
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:6
    master_sync_in_progress:0
    ...
    

如果需要断开复制

slaveof命令不但可以建立复制,还可以在从节点执行 slaveof no one 来断开与主节点复制关系。如果从节点断开了连接,那么当前的redis则会切换为主服务

注意:

  1. 安全
    对于数据比较重要的节点,主节点会通过设置requirepass参数进行密码验证,这时所有的客户端访问必须使用auth 命令实行验证。从节点与主节点的复制链接是通
    过一个特殊标识的客户端来完成,因此需要配置从节点的masterauth参数与主节点密码保持一致,这样从节点才可以正确地链接到主节点并发起复制流程
  2. 从节点只读
    默认情况下 slave-read-only=yes 配置为制度。由于复制只能从主节点到从节点,对于从节点的任何修改主节点都无法感知,修改从节点会造成主从数据不一致。因此没必要就不要动这个配置。
  3. 网络延迟问题
    主从节点一般部署在不同机器上,复制时的网络延迟就成为需要考虑的问题,Redis 为我们提供了repl-disable-tcp-nodelay参数用于控制是否关闭TCP NODELAY,默认关闭,说明如下:
  • 当关闭时,主节点产生的命令数据无论大小都会及时地发送给从节点,这样主从之间延迟会变小,但增加了网络带宽的消耗。适用于主从之间的网络环境
    良好的场景,如同机架或同机房部署。
  • 当开启时,主节点会合并较小的TCP数据包从而节省带宽。默认发送时间间隔取决于Linux的内核,- -般默认为40毫秒。这种配置节省了带宽但增大主从
    之间的延迟。适用于主从网络环境复杂或带宽紧张的场景,如跨机房部署。

注意: 运提部署主从节点时需要考虑网络延迟、带宽使用率、防灾级别等因素,如要求低延迟时,建议同机架或同机房部署并关闭repl-disable-tcp-nodelay;如果考虑高容灾性,可以同城跨机房部署并开启repl-disable-tcp-nodelay.

补充

推荐可以进行如下配置

# logfile "" redis日志
logfile "/redis/log/redis.log"
# dir ./ 数据保存目录
dir "/redis/data"

拓扑

  1. 一主一从
  2. 一主多从
  3. 树状主从结构

原理


根据上图分析大致可以分为6个过程:

  1. 保存主节点(master)

执行slaveof后从节点只保存主节点的地址信息便直接返回,这时建立复制流程还没有开始,在从节点6350执行 info replication 可以看到如下信息:

master_host:192.160.1.50
master_port:6379
master_link_status:up

从节点保存主节点的ip:port,状态是上线状态。我们也可以参考redis的日志查看到复制信息:
如果你开启了redis日志文件的话是可以看到redis的主从连接记录的信息

114:S 28 Apr 2020 18:57:33.459 * Connecting to MASTER 192.160.1.150:6379
114:S 28 Apr 2020 18:57:33.460 * MASTER <-> REPLICA sync started
114:S 28 Apr 2020 18:57:33.460 * Non blocking connect for SYNC fired the event.
114:S 28 Apr 2020 18:57:33.460 * Master replied to PING, replication can continue...
114:S 28 Apr 2020 18:57:33.461 * Trying a partial resynchronization (request 04aa4df6b19fbd0ea4aea54ca856ed91bf6c861c:17027).
114:S 28 Apr 2020 18:57:33.464 * Full resync from master: 0deae7db14cf069bf86408b8abecedf08952c0a8:0
114:S 28 Apr 2020 18:57:33.464 * Discarding previously cached master state.
114:S 28 Apr 2020 18:57:33.537 * MASTER <-> REPLICA sync: receiving 210 bytes from master
114:S 28 Apr 2020 18:57:33.537 * MASTER <-> REPLICA sync: Flushing old data
114:S 28 Apr 2020 18:57:33.537 * MASTER <-> REPLICA sync: Loading DB in memory
114:S 28 Apr 2020 18:57:33.537 * MASTER <-> REPLICA sync: Finished with success
114:S 28 Apr 2020 18:58:31.326 * REPLICAOF would result into synchronization with the master we are already connected with. No operation
performed.
  1. 从节点(slave) 内部通过每秒运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会尝试与该节点建立网络连接


从节点会建立一个 socket 套接字,从节点建立了一个端口为 51234 的套接字,专门用于接受主节点发送的复制命令。从节点连接成功后打印如下日志

如果从节点无法建立连接,定时任务会无限重试直到连接成功或者执行 slaveof no one 取消复制

关于连接失败,可以在从节点执行 info replication 查看 master_link_down_since_seconds 指标,它会记录与主节点连接失败的系统时间。从节点连接主 节点失败
时也会每秒打印如下日志,方便发现问题:

  • Error condition on socket for SYNC: {socket_error_reason}
  1. 发送 ping 命令

连接建立成功后从节点发送 ping 请求进行首次通信, ping 请求主要目的如下

  • 检测主从之间网络套接字是否可用。
  • 检测主节点当前是否可接受处理命令。

如果发送 ping 命令后,从节点没有收到主节点的 pong 回复或者超时,比如网络超时或者主节点正在阻塞无法响应命令,从节点会断开复制连接,下次 定时任务会发起重连


  1. 权限验证

如果主节点设置了 requirepass 参数,则需要密码验证,从节点必须配置 masterauth 参数保证与主节点相同的密码才能通过验证;如果验证失败复制将终 止,从节点重新发起复制流程。

  1. 同步数据集

主从复制连接正常通信后,对于首次建立复制的场景,主节点会把持有的数据全部发送给从节点,这部分操作是耗时最长的步骤。

  1. 命令持续复制

当主节点把当前的数据同步给从节点后,便完成了复制的建立流程。接下来主节点会持续地把写命令发送给从节点,保证主从数据一致性。

注意 主从在同步的过程当中,会把原本的从节点的数据清空

数据同步

概念

  1. 全量复制

用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作,当数据量较大时,会对主从节点和网络造成很 大的开销

  1. 部分复制:

用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果(条件允许),主节点会补发丢失数据给从节点。 因为补发的数据远远小于全量数据,可以有效避免全量复制的过高开销,需要注意的是,如果网络中断时间过长,造成主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制

复制偏移量

参与复制的主从节点都会维护自身复制偏移量。主节点(master)在处理完写入命令后,会把命令的字节长度做累加记录,统计信息在 info relication 中的master_repl_offset 指标中:

127.0.0.1:6379> info replication
# Replication
role:master
...
master_repl_offset:6104

从节点(slave)每秒钟上报自身的复制偏移量给主节点,因此主节点也会保存从节点的复制偏移量,统计指标如下

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.160.1.140,port=6379,state=online,offset=6104,lag=1

从节点在接收到主节点发送的命令后,也会累加记录自身的偏移量。统计信息在 info relication 中的 slave_repl_offset 中

复制积压缓冲区

复制积压缓冲区是保存在主节点上的一个固定长度的队列,默认大小为1MB,当主节点有连接的从节点(slave)时被创建,这时主节点(master)响应写命令时,不但会把命令发送给从节点,还会写入复制积压缓冲区

在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份;除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset) 。由于复制积压缓冲区定长且先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区()。

主节点运行ID

每个Redis节点启动后都会动态分配一个40位的十六进制字符串作为运行ID。运行ID的主要作用是用来唯一识别 Redis节点,比如从节点保存主节点的运行ID识别自己正在复制的是哪个主节点。如果只使用ip+port的方式识别主节点,那么主节点重启变更了整体数据集(如替换RDB/AOF文件),从节点再基于偏移量复制数据将是不安全的,因此当运行ID变化后从节点将做全量复制。可以运行info server命令查看当前节点的运行ID:

127.0.0.1:6379> info server
# Server
redis_version:5.0.7
...
run_id:868a5d49a276620b9f79788a1c894f07bd872f56

需要注意的是Redis关闭再启动,运行的id会随之变化

> redis-cli shutdown
> redis-server redis.conf

Psync命令

从节点使用psync命令完成部分复制和全量复制功能 psync runid offset
流程说明:

  1. 从节点(slave)发送psync命令给主节点,参数runid是当前从节点保存的主节点运行id,如果没有则默认值为 ?, 参数offset是当前从节点保存的复制偏移量,如果是第一次参与复制则默认值为-1
  2. 主节点(master)根据psync参数和自身数据情况决定响应结果:
    • 如果回复+FULLRESYNC {runid} {offset}, 那么从节点将厨房全量复制流程。
    • 如果回复+CONTINUE,从节点将触发部分复制流程。
    • 如果回复+ERR,说明主节点版本低于Redis2.8

全量复制流程

注意: 从节点在载入主节点的数据之前要先将从节点老数据清除

全量复制是Redis最早支持的复制方式,也是主从第一次建立复制时必须经历的阶段。触发全流量复制的命令是sync和psync

流程说明

  1. 发送psync命令进行数据同步,由于是第一次进行复制,从节点没有复制偏移量和主节点的运行id,所以发送psync ? -1

  2. 主节点根据psync ? -1解析出当前为全量复制,回复+FULLRESYNC响应(主机会向从机发送 runid 和 offset,因为 slave 并没有对应的 offset,所以是全量复制)

  3. 从节点接收主节点的响应数据保存运行ID和偏移量offset(从机 slave 会保存 主机master 的基本信息 save masterInfo)

  4. 主节点收到全量复制的命令后,执行bgsave(异步执行),在后台生成RDB文件(快照),并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行 的所有写命令

  5. 主节点发送RDB文件给从节点,从节点把接收到的RDB文件保存在本地并直接作为从节点的数据文件,接收完RDB后从节点打印相关日志,可以在日志中查看主节点发送的数据量(主机send RDB 发送 RDB 文件给从机)

    MASTER <-> REPLICA sync: Flushing old data

    注意!对于数据量较大的主节点,比如生成的RDB文件超过6GB以上时要格外小心。传输文件这一步操作非常耗时,速度取决于主从节点之间网络带宽,通过细致分析Full resync和MASTER <-> SLAVE这两行日志的时间差,可以算出RDB文件从创建到传输完毕消耗的总时间。如果总时间超过repl-timeout所配置的值(默认60秒),从节点将放弃接受RDB文件并清理已经下载的临时文件,导致全量复制失败;针对数据量较大的节点,建议调大repl-timeout参数防止出现全量同步
    数据超时;
    例如对于千兆网卡的机器,网卡带宽理论峰值大约每秒传输100MB,在不考虑其他进程消耗带宽的情况下,6GB的RDB文件至少需要60秒传输时间,默认配置下,极易出现主从数同步超时。

  6. 对于从节点开始接收RDB快照到接收完成期间,主节点仍然响应读写命令,因此主节点会把这期间写命令数据保存在复制客户端缓冲区内,当从节点加载完RDB文件后,主节点再把缓冲区内的数据发送给从节点,保证主从之间数据致性。(发送缓冲区数据)

  7. 从节点接收顽主节点传送来的全部数据后会清空自身旧数据(刷新旧的数据,从节点在载入主节点的数据之前要先将老数据清除)

  8. 从节点清空数据后开始加载RDB文件,对于较大的RDB文件,这一步操作依然比较消耗时间,可以通过计算日志之间的实际差来判断加载RDB的总消耗时间(加载 RDB 文件将数据库状态更新至主节点执行bgsave时的数据库状态和缓冲区数据的加载。)

    114:S 28 Apr 2020 18:57:33.537 * MASTER <-> REPLICA sync: Loading DB in memory
    114:S 28 Apr 2020 18:57:33.537 * MASTER <-> REPLICA sync: Finished with success

  9. 从节点成功加载完RDB后,如果当前节点开启了AOF持久化的功能,它会立刻做bgrewriteeaof的操作,为了保证全量复制后AOF持久化文件立刻可用。

通过分析全量复制的所有流程,全量制是一个非常耗时费力的操作。他的实际开销主要包括:

  • 主节点bgsave时间
  • RDB文件网络传输时间。
  • 从节点清空数据时间
  • 从节点加载RDB的时间
  • 可能的AOF重写时间

部分复制流程

部分复制是 Redis 2.8 以后出现的,之所以要加入部分复制,是因为全量复制会产生很多问题,比如像上面的时间开销大、无法隔离等问题, Redis 希望能够在master 出现抖动(相当于断开连接)的时候,可以有一些机制将复制的损失降低到最低

流程说明:

  1. 当主从节点之间网络出现中断时,如果超过repl-timeout时间,主节点会认为从节点出问题了并断开复制链接(如果网络抖动(连接断开 connection lost))
  2. 主从连接中断期间主节点依然响应命令,但因复制链接中断命令无法发送给从节点不过主节点内部存在的复制积压缓存去,依然可以保存一段时间的写命令数
    据,默认最大缓存1MB(主机master 还是会写 replbackbuffer(复制缓冲区))
  3. 当主从节点网络恢复后,从节点会再次连上主节点。(从机slave 会继续尝试连接主机)
  4. 当主从连接恢复后,由于从节点之前保存了自身已复制的偏移量和主节点的运行id。因此会把他们当作psync参数发送给主节点,要求进行部分复制操作。(从
    机slave 会把自己当前 runid 和偏移量传输给主机 master,并且执行 pysnc 命令同步)
  5. 主节点接到psync命令后首先核对参数的runid,如果 master 发现你的偏移量是在缓冲区的范围内,根据参数offset在缓冲区查找复制内内,如果在偏移量之后
    的数据存在缓存区中,则对从节点发送continue表示可以进行部分复制
  6. 主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。(同步了 offset 的部分数据,所以部分复制的基础就是偏移量offset)

心跳

主节点在建立成功后会维护这长连接彼此发送心跳检测

  1. 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信,通过client list命令查看复制相关客户端信息,主节点的连接状态为flags=M,从节点连接
    状flags=S
  2. 主节点默认每隔10秒对从节点发送ping命令,判断从节点的存活性和连接状态。可通过参数repl-ping-slave-period控制发送频率。
  3. 从节点在主线程中每隔1秒发送replconf ack {offset} 命令,给主节点上报自身当前的复制偏移量。

缓冲大小调节

由于缓冲区长度固定且有限,因此可以备份的写命令也有限,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。反过 来说,为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size)来设置; 例如 如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见, 可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。

读写分离

读流量分摊到从节点。这是个非常好的特性,如果一个业务只需要读数据,那么我们只需要连一台 slave 从机读数据。

做个整体的规划:
一主两从:

容器名称 容器IP地址 映射端口号 宿主机IP地址 服务运行模式
redis5_m_150 xx.xx.xx.150 6350 -> 6379 xxx master
redis5_s_140 xx.xx.xx.140 6340 -> 6379 xxx slave
redis5_s_130 xx.xx.xx.130 6330 -> 6379 xxx slave
docker run -itd -v /redis_2004/masterandslave/master:/redis -p 6350:6379 --network=redis5sm --ip=192.160.1.150 --name redis5_m_150 redis5asm
sh
docker run -itd -v /redis_2004/masterandslave/slave_130:/redis -p 6330:6379 --network=redis5sm --ip=192.160.1.130 --name redis5_s_140
redis5asm sh
docker run -itd -v /redis_2004/masterandslave/slave_140:/redis -p 6340:6379 --network=redis5sm --ip=192.160.1.140 --name redis5_s_130
redis5asm sh

redis学习笔记(2)之redis主从详解相关推荐

  1. JDBC学习笔记02【ResultSet类详解、JDBC登录案例练习、PreparedStatement类详解】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

  2. 小猫爪:i.MX RT1050学习笔记26-RT1xxx系列的FlexCAN详解

    i.MX RT1050学习笔记26-RT1xxx系列的FlexCAN详解 1 前言 2 FlexCAN简介 2.1 MB(邮箱)系统 2.1.1 正常模式下 2.1.2 激活了CAN FD情况下 2. ...

  3. IP地址和子网划分学习笔记之《IP地址详解》

    在学习IP地址和子网划分前,必须对进制计数有一定了解,尤其是二进制和十进制之间的相互转换,对于我们掌握IP地址和子网的划分非常有帮助,可参看如下目录详文. IP地址和子网划分学习笔记相关篇章: 1.I ...

  4. 我的学习笔记——CSS背景渐变(Gradients)详解

    我的学习笔记--CSS背景渐变(Gradients)详解 一.线性渐变(Linear Gradients) 1.语法 background-image: linear-gradient(directi ...

  5. IP地址和子网划分学习笔记之《子网划分详解》

    一,子网划分概述 IP地址和子网划分学习笔记相关篇章: 1.IP地址和子网划分学习笔记之<预备知识:进制计数> 2.IP地址和子网划分学习笔记之<IP地址详解> 3.IP地址和 ...

  6. redis学习笔记(7)之redis哨兵详解

    redis哨兵详解 sentinel命令 客户端连接 素材代码 思路 实现过程 哨兵的切换实现原理 发布订阅基础 哨兵的实现原理 部署建议 需要关注的问题 代码流程 内容来源为六星教育,这里仅作为学习 ...

  7. redis学习笔记(6)之redis哨兵

    redis哨兵 redis哨兵初识 基础概念 主从复制的问题 redis 哨兵的高可用性 redis哨兵安装和部署 部署结构 内容来源为六星教育,这里仅作为学习笔记 redis哨兵初识 redis的主 ...

  8. redis学习笔记(5)之redis内存优化

    redis内存优化 配置优化 Linux 配置优化 Redis配置优化 缩减键值对象 命令处理 缓存淘汰优化 动态改配置命令 设置最大内存 设置淘汰策略 内存淘汰策略 如何选择淘汰策略 内容来源为六星 ...

  9. 【Redis学习笔记】13.Redis 主从复制

    Redis 主从复制 1. Redis 主从复制特性 2. Redis 主从复制流程 3. Redis 主从复制操作 3.1. 快速部署Redis实例 3.2. 配置主从复制 3.3. 查看主从复制 ...

最新文章

  1. AppStore 拒绝审核原因:PLA 2.3
  2. error D8021 :无效的数值参数“/Wno-cpp” cython_bbox
  3. 自编码AutoEncoder 及PyTorch 实现
  4. 【Python金融量化 6- 100 】、六、蒙特卡洛预测微软股票
  5. 在MySQL登录时出现Access denied for user ‘root‘@‘localhost‘ (using password: YES)
  6. MySQL Internals Manual
  7. Sql Server中查看/修改identity(自增列)的值
  8. jdi屏幕斜纹_荣耀V10屏幕有斜纹问题,有人甚至因此退货,真的这么严重?
  9. 简历python技能怎么写_简历怎么写?列出这10项重要的工作技能
  10. python实现字典树的插入、查找功能并基于pickle模块持久化存储字典树
  11. 基于SSM的电影购票系统
  12. Android 布局优化之include与merge
  13. 【计算机考研408强化-操作系统】1. 操作系统的基本概念
  14. 联想凌拓“开业大吉” 是试水还是全面变革的前兆?
  15. 鲁大师发布2022半年报手机UI排行榜,vivo OriginOS成为最流畅UI
  16. 不等式解集怎么取_(√)口诀巧取不等式组的解集
  17. 送给1985年左右的朋友 怀念小时候的我们
  18. ADS1.2 Error:(Fatal) L6002u:could not open file C:/...
  19. pytorch中x.norm(p=2,dim=1,keepdim=True)的理解
  20. Flutter:WebView和H5通信

热门文章

  1. Nuxt - 每个页面单独设置 SEO 相关标签及网页标题、图标等(页面配置 head)
  2. “支付宝卡通”服务需要和银行签约才能开通。目前有以下银行支持“支付宝卡通”服务
  3. Charles手机安装教程(荣耀手机亲测)
  4. UVa Q10137: The Trip (旅行)
  5. 货运APP开发面临市场的考验
  6. ThinkPHP5.0 根据固定模板生成个人名片
  7. 什么是MaxCompute
  8. 阿里云短信验证(代码)demo完整教程
  9. 005-关于win10系统更新后,无法登录你的账户,通常可以通过请注销。。。。。
  10. 可逆数据隐藏python实现(Reversible Data Hiding)