redis 无盘复制(redis repl-diskless-sync)
  4fC8pwYp1Qxy 22天前 26 0

无盘复制的需求背景

redis在启动后自动生成一个唯一的标识符run_id,这个run_id在持久化的时候存在于RDB文件中(如果有启用RDB或者做了RBD备份操作),但是并不存在与AOF文件中(包括混合是持久化文件),如果下次重启从RDB加载数据,那么这个run_id可以保存。 如果同时启用了RDB和AOF持久化,redis重启时会优先加载AOF文件,如果从AOF加载,那么这个run_id会重新生成。
redis复制环境下(不管是简单的主从复制,Sentinel,Cluster)主从节点之间依赖run_id做身份标识,当redis重启后,如果不是从RDB中加载的,其身份标识run_id会发生变化,当前实例相当于一个全新的节点, 此时会进行一个全量的同步操作(比如从节点重启后,run_id发生了变化,从节点的身份会变为一个“全新的节点”,会向主节点做一次全量同步的请求),以从节点重启后run_id重新生成导致的全量同步步骤大概如下:
----》从节点请求全量同步
--------》主节点生成RDB文件到磁盘(主节点磁盘写操作)
----------》主节点发送RDB文件到从节点(主节点磁盘读操作)
------------》从节点接收主节点发送的RDB文件到本地磁盘(从节点磁盘写操作)
--------------》从节点接从本地接收的RDB文件到加载数据到磁盘(从节点磁盘读操作)
如果是主节点重启,从AOF中加载持久化的数据,那么会从节点会做类似的全量同步操作
可见全量同步过程中,会在主节点上经历一次磁盘写操作和一次磁盘读操作,从节点上经历一次磁盘写操作和磁盘读操作,如果磁盘速度跟不上,可能会拉长全量同步的时长,因此无盘同步的需求就出现了(假设节点间网络没有瓶颈)。
 

相关参数

影响主节点的参数

repl-diskless-sync 

该参数默认值为no,也即从节点请求全量复制的时候,主节点上不开启无盘复制,先通过bgsave做持久化,然后传输RDB文件到从节点,

全量同步的可以通过两种方式进行:
  • 基于磁盘的复制:Redis主节点会创建一个新的进程,在磁盘上写入RDB文件。之后,父进程会逐步将文件传输给副本。
  • 无磁盘复制:Redis主节点创建的新进程会直接将RDB文件写入副本的套接字,完全不涉及磁盘操作。
在使用基于磁盘的复制时,当RDB文件正在生成时,其他的副本可以排队,并能在当前子进程完成RDB文件生成后立刻使用这个文件。
在磁盘速度慢而网络速度快(带宽大)的情况下,无磁盘复制表现得更好。这是因为无磁盘复制避免了磁盘I/O操作的瓶颈,可以更快地通过网络直接将数据发送给副本。而基于磁盘的复制方式在传输前需要将数据写入磁盘,这在磁盘性能不佳的情况下可能会成为性能瓶颈。因此,在网络速度快而磁盘速度慢的环境中,选择无磁盘复制通常是一个更好的选择。

repl-diskless-sync-delay

默认值为5,单位为秒,该参数只有开启了repl-diskless-sync 为yes的时候才会生效
在使用无磁盘复制时,一旦传输开始,新到达的副本会被排队,直到当前传输结束,新的传输才会开始。
当使用无磁盘复制时,主节点会等待一个时间段repl-diskless-sync-delay(以秒为单位)再开始传输,这样做的目的是希望多个副本能够在这段时间内到达,从而使传输过程可以并行化。

repl-diskless-sync-max-replicas 

该参数默认值为0
当使用延迟启用无磁盘复制时,如果连接的副本达到预期的最大数量,则可以在达到最大延迟之前启动复制。默认值为0表示没有定义最大值,Redis将等待完整的repl-diskless-sync-delay。

影响从节点的参数

repl-diskless-load

该参数默认为disabled。
副本可以直接从socket中加载它从复制链接读取的RDB,直接加载到内存或者暂存在本地磁盘,完整地接收主节点的RDB文件之后再加载到内存。
在许多情况下,磁盘比网络慢,存储RDB到磁盘和加载RDB文件到内存,可能会增加复制时间(甚至会增加主服务器的Copy on Write内存和副本缓冲区)。但是,当直接从套接字解析RDB文件时,为了避免数据丢失,只有在新数据集完全加载到内存中时才会刷新当前数据集,这将导致更高的内存使用。出于这个原因,我们有以下选项:
  • "disabled"  :(从节点)不使用无磁盘加载(首先将rdb文件存储到磁盘),特别说明,这是一个双重否定句,等于是肯定句,字面意思很别扭,意思是完整地将RDB写入磁盘文件之后,再从磁盘加载到内存。
  • "swapdb"  :在直接从套接字解析数据时,将当前数据库内容保存在RAM中。这种模式下的副本可以在复制过程中继续服务当前数据集,除非它们不能识别出主数据集具有来自相同复制历史的数据集。注意,这需要足够的内存(理论上需要双倍的内存,一份是从主节点接收的RDB文件,一份是从RDB文件转换为当前实例的内存),如果没有,将会存在OOM的风险。
  • "on-empty-db"  :只在当前数据集为空时使用无磁盘加载。这样更安全,避免了在复制过程中同时加载旧数据集和新数据集。

无盘复制过程

一个无盘复制的日志大概如下

 从节点的日志

33300:S 06 Apr 2024 19:29:32.276 * Connecting to MASTER ***.***.***.***:***              #从节点连接至主节点
33300:S 06 Apr 2024 19:29:32.276 * MASTER <-> REPLICA sync started
33300:S 06 Apr 2024 19:29:32.276 * Non blocking connect for SYNC fired the event.
33300:S 06 Apr 2024 19:29:32.276 * Master replied to PING, replication can continue...
33300:S 06 Apr 2024 19:29:32.277 * Partial resynchronization not possible (no cached master)    #从节点重启后,run_id发生变化,作为一个新的从节点,需要做全量同步
33300:S 06 Apr 2024 19:29:37.953 * Full resync from master: f2ec97e11ec65d3e9ecdfd822b93905a9fac37a3:911741
33300:S 06 Apr 2024 19:29:37.958 * MASTER <-> REPLICA sync: receiving streamed RDB from master with EOF to parser #从节点从socket中接收主节点的全量RDB数据
33300:S 06 Apr 2024 19:29:37.958 * MASTER <-> REPLICA sync: Loading DB in memory
33300:S 06 Apr 2024 19:29:37.958 * Loading RDB produced by version 7.0.11
33300:S 06 Apr 2024 19:29:37.958 * RDB age 0 seconds
33300:S 06 Apr 2024 19:29:37.958 * RDB memory usage when created 62.40 Mb
33300:S 06 Apr 2024 19:30:25.667 * Done loading RDB, keys loaded: 191498, keys expired: 0.
33300:S 06 Apr 2024 19:30:25.667 * MASTER <-> REPLICA sync: Swapping active DB with loaded DB      
33300:S 06 Apr 2024 19:30:25.667 * MASTER <-> REPLICA sync: Discarding old DB in background  
33300:S 06 Apr 2024 19:30:25.667 * MASTER <-> REPLICA sync: Finished with success  #从节点加载全量数据

主节点的日志

32489:M 06 Apr 2024 19:29:32.277 * Replica ***.***.***.***:*** asks for synchronization    #从节点请求主节点做全量复制 32489:M 06 Apr 2024 19:29:32.277 * Full resync requested by replica ***.***.***.***:*** 32489:M 06 Apr 2024 19:29:32.277 * Delay next BGSAVE for diskless SYNC              #主节点由于diskless复制,并没有做bgsave持久化操作 32489:M 06 Apr 2024 19:29:37.952 * Starting BGSAVE for SYNC with target: replicas sockets   #主节点以socket网络传送方式传递全量数据 32489:M 06 Apr 2024 19:29:37.954 * Background RDB transfer started by pid 33306 33306:C 06 Apr 2024 19:30:25.186 * Fork CoW for RDB: current 1 MB, peak 1 MB, average 1 MB 32489:M 06 Apr 2024 19:30:25.186 # Diskless rdb transfer, done reading from pipe, 1 replicas still up. 32489:M 06 Apr 2024 19:30:25.276 * Background RDB transfer terminated with success 32489:M 06 Apr 2024 19:30:25.276 * Streamed RDB transfer with replica ***.***.***.***:*** succeeded (socket). Waiting for REPLCONF ACK from slave to enable streaming 32489:M 06 Apr 2024 19:30:25.276 * Synchronization with replica ***.***.***.***:*** succeeded

 当从节点以"swapdb"在加载数据的过程中(一边接收主节点socket数据一边载入当前实例中),当前实例不可访问

 
 
 对于Redis集群模式,不管是sentinel还是cluster,主从节点的身份都是相对的,都可以在故障发生时做主从切换,因此如果想要实现无盘复制,这几个参数需要再主从节点同时配置。
repl-diskless-sync yes
repl-diskless-sync-delay 15
repl-diskless-sync-max-replicas 0 
repl-diskless-load disabled #如果有足够多的内存,使用swapdb

 无盘复制注意事项

1,较小的数据没必要使用无盘复制,想对无盘复制,传统的复制是生成RDB文件到磁盘,然后传输RDB,这个RDB是经过高度压缩的,其体积并不会太大
2,基于1,如果磁盘性能较高,生成RDB文件的速度较快的话,在网络中传输一个较小的,经过压缩的RDB文件不一定会很慢
3,相比基于经过压缩的RDB复制,基于无盘复制需要传输整个内存中的RDB数据,是一个非压缩的数据集,期代价需要在网络中是传输较多的数据,要求网络性能较高,延迟较高的网络无法提现无盘复制的优势

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 22天前 0

暂无评论

推荐阅读
  0A7yydzHqvH3   2024年03月02日   30   0   0 NoSQL
  VlRy1zDaWnkA   2024年03月20日   38   0   0 NoSQL
  0A7yydzHqvH3   2024年03月01日   34   0   0 NoSQL
  kZLEadpmxZsY   2024年03月10日   64   0   0 NoSQL
  l3iKMwY9XZmO   2024年01月10日   13   0   0 NoSQL
  Jtgzt2RY5Ua9   2024年02月23日   54   0   0 NoSQL
  AwEx8gO5M96i   2024年01月21日   14   0   0 NoSQL
  UNPmS8bQOMQ9   2024年02月19日   47   0   0 NoSQL
  2Qcbx4bZA80L   2024年03月15日   29   0   0 NoSQL
4fC8pwYp1Qxy