您的位置:首页 > 数据库 > Redis

Redis之主从同步

2019-11-01 16:32 106 查看

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

CAP原理

  • CAP原理好比分布式领域的牛顿定律,它是分布式存储的理论基石。
  • C - Consistent ,一致性
  • A - Availability ,可用性
  • P - Partition tolerance ,分区容忍性
  • 分布式系统的节点往往都是分布在不同的机器上进行网络隔离开的,这意味着必然会有网络断开的风险,这个网络断开的场景的专业词汇叫着「网络分区」。

  • 在网络分区发生时,两个分布式节点之间无法进行通信,我们对一个节点进行的修改操作将无法同步到另外一个节点,所以数据的「一致性」将无法满足,因为两个分布式节点的数据不再保持一致。除非我们牺牲「可用性」,也就是暂停分布式节点服务,在网络分区发生时,不再提供修改数据的功能,直到网络状况完全恢复正常再继续对外提供服务。

  • 在网络分区发生的时候,一致性和可用性两难全。

什么是主从复制

  • 主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave),数据的复制是单向的,只能由主节点到从节点。

    默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点

主从复制的作用

  • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  • 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  • 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
  • 读写分离:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量;
  • 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础

主从复制启用(主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。)

     从节点开启主从复制,有3种方式:

  • 配置文件: 在从服务器的配置文件中加入:slaveof <masterip> <masterport>     (slaveof是异步命令,从节点完成主节点ip和port的保存后,向发送slaveof命令的客户端直接返回OK,实际的复制操作在这之后才开始进行
  • 启动命令: redis-server启动命令后加入 --slaveof <masterip> <masterport>
  • 客户端命令: Redis服务器启动后,直接通过客户端执行命令:slaveof <masterip>
    <masterport>,则该Redis实例成为从节点。
  • 通过  info replication 命令可以看到复制的一些信息

主从复制原理

  • 主从复制过程大体可以分为3个阶段:连接建立阶段(即准备阶段)、数据同步阶段、命令传播阶段。

  •  

    在从节点执行 slaveof 命令后,复制过程便开始运作,下面图示大概可以看到,
    从图中可以看出复制过程大致分为6个过程
  • 主从配置之后的日志记录也可以看出这个流程

    1)保存主节点(master)信息。
    执行 slaveof 后 Redis 会打印如下日志:

    2)从节点(slave)内部通过每秒运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会尝试与该节点建立网络连接

    从节点与主节点建立网络连接

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

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

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

    # Error condition on socket for SYNC: {socket_error_reason}

    3)发送 ping 命令。
    连接建立成功后从节点发送 ping 请求进行首次通信,ping 请求主要目的如下:
    ·检测主从之间网络套接字是否可用。
    ·检测主节点当前是否可接受处理命令。
    如果发送 ping 命令后,从节点没有收到主节点的 pong 回复或者超时,比如网络超时或者主节点正在阻塞无法响应命令,从节点会断开复制连接,下次定时任务会发起重连。

    从节点发送的 ping 命令成功返回,Redis 打印如下日志,并继续后续复制流程:

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

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

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

数据同步阶段

    全量复制

  • Redis通过psync命令进行全量复制的过程如下:

    (1)从节点判断无法进行部分复制,向主节点发送全量复制的请求;或从节点发送部分复制的请求,但主节点判断无法进行全量复制;具体判断过程需要在讲述了部分复制原理后再介绍。

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

    (3)主节点的bgsave执行完成后,将RDB文件发送给从节点;从节点首先清除自己的旧数据,然后载入接收的RDB文件,将数据库状态更新至主节点执行bgsave时的数据库状态

    (4)主节点将前述复制缓冲区中的所有写命令发送给从节点,从节点执行这些写命令,将数据库状态更新至主节点的最新状态

    (5)如果从节点开启了AOF,则会触发bgrewriteaof的执行,从而保证AOF文件更新至主节点的最新状态

    下面是执行全量复制时,主从节点打印的日志;可以看出日志内容与上述步骤是完全对应的。

    部分复制

  • 复制偏移量:主从节点各自维护一个offset,主节点的offset表示已经向从节点传输的字节数,从节点的offset表示已经接受的字节数。如果两个offset相同,那么就是表示主从数据库状态一致。如果offset不同,则不一致,此时可以根据两个offset找出从节点缺少的那部分数据。例如,如果主节点的offset是1000,而从节点的offset是500,那么部分复制就需要将offset为501-1000的数据传递给从节点。而offset为501-1000的数据存储的位置,就是下面要介绍的复制积压缓冲区
  • 复制积压缓存区:复制积压缓存区是由主节点维护的,固定长度的,先进先出的队列,默认大小为1M。当主节点有从节点创建的时候,其作用就是备份主节点最近发给从节点的数据。由于复制积压缓存区长度固定有限,先进先出,所有如果主从offset差距过大的时候,那么最先的命令就会被挤出丢失,那么只能执行全量复制。
  1. 从节点将offset发送给主节点后,主节点根据offset和缓冲区大小决定能否执行部分复制:

  2. 如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;
  3. 如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制。
  • 服务器运行ID(runid):每个Redis节点(无论主从),在启动时都会自动生成一个随机ID(每次启动都不一样),由40个随机的十六进制字符组成;runid用来唯一识别一个Redis节点
  1. 主从节点初次复制时,主节点将自己的runid发送给从节点,从节点将这个runid保存起来;当断线重连时,从节点会将这个runid发送给主节点;主节点根据runid判断能否进行部分复制:

  2. 如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况);
  3. 如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制

参考文章:  https://segmentfault.com/a/1190000018268350?utm_source=tag-newest

                 https://www.geek-share.com/detail/2741147780.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Redis