mysql、redis、kafka的复制功能总结

文章目录

  • mysql、redis、kafka的复制功能
    • mysql的复制
      • 异步复制
      • 完全同步复制
      • 半同步复制
    • redis的复制
      • 完整重同步
      • 部分重同步
    • kafka的复制
      • 首领副本(leader)
      • 跟随者副本(follower)
      • 同步副本(ISR)
    • 参考文献

mysql、redis、kafka的复制功能

​ 上次面试中面试官问到了一个mysql的复制功能,当时答上来了主从复制的主要流程,当问到完全同步复制和半同步复制时,脑海中有点印象,但是却记不清了,而且还把redis的完整重同步和部分重同步搞混了。所以这里把mysql、redis、kafka的复制功能做一个总结,避免看过的概念互相混淆。

​ 这里写出来仅供大家参考,文中可能有些错别字或者描述不准确、不到位的地方,欢迎大家批评指正。

mysql的复制

​ 复制(replication)是mysql提供的一种高可用高性能的解决方案,其工作原理分为以下几个步骤:

​ 1、主服务器(master)将数据更改的操作记录写到二进制redo日志(binlog)中

​ 2、从服务器(slave)将主服务器中的二进制日志复制到自己的中继日志(relay log)中

​ 3、从服务器重做中继日志中的日志,把更改应用到自己的数据库中,保证数据的最终一致性

​ 复制的原理实际上就是一个完全备份加上二进制日志的备份还原,为了保证从服务器的性能,从服务器开启了两个线程:一个是I/O线程,负责接收主服务器的二进制日志,并将其复制到自己的中继日志中;另外一个是sql线程,负责读取中继日志中的记录并执行sql以达到主从数据库的一致性。

异步复制

​ 为了保证主服务器的性能和响应及时性,mysql默认的复制是异步的,而并不是实时进行的。主服务器在执行完客户端提交的事务后,立即将结果返回给客户端,而并不会关心从服务器是否已经接收并处理。这就带来主从服务器上的执行时延,如果主服务器的压力很大,那么可能导致只从服务器之间存在较大的时延,一旦主服务器宕机了,此时强行提升从服务器作为主服务器,会导致数据的缺失。

完全同步复制

​ 为了解决异步复制可能导致的主从服务器数据不一致问题,mysql5.5版本开始支持完全同步复制策略。该策略下,当主服务器执行完一个事务后,从服务器也执行成功时才返回给客户端。因为需要等待所有的从服务器执行完事务才能将结果返回给客户端,所以主从复制的性能会下降很多。

半同步复制

​ 半同步复制是介于异步复制和完全同步复制之间的一种折中方案。当主服务器执行完一个事务时,只需要有一台从服务器执行完这个事务便可以返回,这样和完全同步复制相比性能就会有一个大大的提升;同时,半同步复制能保证至少有一个从服务器与主服务器中的数据完全一致,即使主服务器宕机,也可以直接将这个从服务器提升为主服务器。

redis的复制

​ redis的复制功能分为同步命令传播两个操作:

  • 同步

    同步操作用于将从服务器的状态更新至主服务器目前所处的状态。

    从服务器对主服务器的同步操作需要向主服务器发送SYNC命令来完成,主要步骤如下:

    1. 从服务器向主服务器发送SYNC命令
    2. 收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区来记录从现在开始执行的所有写命令
    3. 当主服务器的BGSAVE命令执行完毕后, 主服务器会将生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时所处的状态
    4. 主服务器将记录在缓冲区中的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态
  • 命令传播

    ​ 命令传播则用于在主服务器的数据库状态被修改,导致主从服务器的状态不一致时,让主从服务器的数据库状态回到一直状态。

    ​ 主服务器会将自己执行的写命令,也就是造成主从服务器数据库状态不一致的命令,发送给从服务器执行,当从服务器执行了相同的命令后,主从服务器的数据库重新回到一致性状态。

    ​ redis的SYNC命令会导致断线重复制的低效问题,所以从2.8版本开始,使用PSYNC命令代替SYNC命令来执行复制时的低效问题。PSYNC命令具有完整重同步和部分重同步两种模式。

完整重同步

​ 完整重同步用于处理初次复制情况,其执行步骤和SYNC命令的执行步骤基本一样,都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区中的所有写命令实现的。

部分重同步

​ 部分重同步用于处理断线后的重复制情况,当从服务器在断线后重新连接到主服务器时,如果条件允许,主服务器可以将主次服务器断开连接期间执行的写命令发送给从服务器,从服务器执行这些写命令,就可以使从服务器数据库更新至主服务器数据库所在的状态。

​ 部分重同步的功能主要由三个部分构成:

  • 主服务器的复制偏移量和从服务器的复制偏移量
    如果主从服务器的复制偏移量相同,则主从服务器处于一直状态。

  • 主服务器的复制积压缓冲区
    复制积压缓冲区是由主服务器维护的一个固定长度先入先出的队列,默认大小为1MB。当从服务器进行命令传播时,它不仅会将所有的写命令发送给所有的从服务器,还会将写命令入队到复制积压缓冲区。
    ​ 从服务器会通过PSYNC命令将自己的复制偏移量offset告诉主服务器,如果offset偏移量之后的数据还存在于主服务器的复制积压缓冲区中,则主服务器将对从服务器执行部分重同步操作,否则将会对从服务器执行完整重同步操作。

  • 服务器的运行ID
    ​每个redis服务器,不管是主服务器还是从服务器都会有一个服务器运行ID,这个ID在服务器启动时自动生成,由40个随机的16进制字符组成。
    ​当从服务器对主服务器进行初次复制时,从服务器会将主服务器的运行ID保存下来。当从服务器断线并重连到一个主服务器时,从服务器会向主服务器发送之前保存的服务器ID,若从服务器保存的运行ID与当前连接的主服务器运行ID相同,说明从服务器断线前复制的就是这个主服务器,主服务器可以尝试执行部分重同步操作;相反地,若从服务器保存的服务器ID与当前连接的主服务器的运行ID不同,则主服务器执行完整重同步操作。

kafka的复制

​ 备份机制的出现大大提高了Kafka集群的可靠性和稳定性。有了备份机制后,Kafka允许集群中的节点挂掉后而不影响整个集群工作。
​ kafka使用主题来组织数据,每个主题被分为若干个分区,每个分区有多个副本,这些副本被保存在broker上,每个broker可以保存成百上千个属于不同主题和分区的副本。

首领副本(leader)

​ 每个分区都有一个首领副本,为了保证一致性,所有的生产者请求和消费者请求都会经过首领副本。

跟随者副本(follower)

​ 首领副本以外的副本都是跟随者副本。跟随者副本不处理来自客户端的请求,它们唯一要做的事情就是从首领副本那里复制消息,保持与首领副本一致的状态。如果首领副本挂了,其中一个跟随者副本就会被提升为新的首领副本。

同步副本(ISR)

ISR(in-sync replicas)在leader失效的时候,有可能会被选中为leader。分区的首领副本是同步副本,持续获得最新数据的跟随者副本才能算是同步副本。跟随者副本只有满足以下条件才能算是同步副本:

  1. 与zookeeper之间保持了一个活跃的会话,也就是必须在过去的6s(可配置项)内向zookeeper发送过心跳
  2. 在过去10s(可配置项)内从leader节点获取过消息
  3. 在过去10s(可配置项)内从leader节点获取过最新的数据,且时间上几乎是同步的

​ 当某个主题的分区初始化创建时,每个副本都在ISR集合中。当新消息发布后,leader提交消息前会一直等待直到所有ISR副本收到消息。如果某个follower副本故障,它将会被从ISR中移除。leader会继续提交新的消息,只不过ISR数量与分区创建时的副本数量相比变少了。

参考文献

  1. mysql技术内幕:InnoDB存储引擎(第二版)
  2. redis设计与实现
  3. kafka权威指南

你可能感兴趣的:(后台技术)