关于redis主从同步的信息

本篇文章给大家谈谈redis主从同步,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

Redis的同步机制

Redis可以使用主从同步,从从同李斗步。第一次同步时,主节点做一次bgsave,哪搜磨并同时将后续修改操作记录到内存buffer,待完成后将rdb文件全量同步到复制漏握节点,复制节点接收完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。

redis 主从同步-master端

redis数据淘汰原理

redis过期数据删除策略

redis server事件模型

redis cluster mget 引发的讨论

redis 3.x windows 集群搭建

redis 命令执行过程

redis string底层数据结构

redis list底层数据结构

redis hash底层数据结构

redis set底层数据结构

redis zset底层数据结构

redis 客户端管理

redis 主从同步-slave端

redis 主从同步-master端

redis 主从超时检测

redis aof持久化

redis rdb持久化

redis 数据恢复过程

redis TTL实现原理

redis cluster集群建立

redis cluster集群选主

 redis 主从同步的过程始于一系列类似tcp三次握手兄高族的过程,归于"sync/psync"命令。分析redis主从同步master端的处理逻辑需要从syncCommand的函数开始进行分析。

 redis 主从同步过程中 master的执行内容 包括:

 整个处理逻辑主要分为处理 部分同步命令psync 和 全量同步命令sync ,整个交互过程如下

需要针对触发bgsave命令的部分作下详细说明,因为这个是核心的关键点:

 羡弊判断能够通过部分数据同步实现的逻辑很简单,主要从两个维度进行判断:

 众所周知rdb文件生成是内部fork新的线程去执行rdb生成过程的,通过rdbSaveBackground的函数可以看出来念孙内部通过fork()去实现rdb文件的生成过程。

  在fork的线程当中执行rdbSave实现rdb文件的生成过程。

  rdb文件的生成过程其实挺简单的 ,大概流程如下:

 通过检查server.rdb_child_pid或者server.aof_child_pid确认是否执行rdb文件生成或者aof文件写入。

 bgsave完成后我们执行updateSlavesWaitingBgsave来实现rdb数据的同步。

  在updateSlavesWaitingBgsave过程中我们把和slave连接的socket注册写事件到eventLoop当中且回调函数为sendBulkToSlave,通过该回调函数实现rdb文件的传输。

  可以看出来整个同步过程中我们会同步master到所有的slave节点,注意是所有的slave节点。

  sendBulkToSlave内部主要实现两个事情,都是和数据传输有关:

[img]

脑裂以及Redis主从同步中的坑

所谓的脑裂,就是指在主从集群中,同时有两个主节点,它们都能接收写请求。而脑裂最直接的影响,就是客户端不知道应该往哪个主节点写入数据,结果就是不同的客户端会往不同的主节点上写入数据。而且,严重的话,脑裂会进一步导致数据丢失。

主库是由于某些原因无法处理请求,也没有响应哨兵的心跳,才被哨兵错误地判断为客观下线的。结果,在被判断下线之后,原主库又重新开始处理请求了,而此时,哨兵还没有完成主从切换,客户端仍然可以和原主库通信,客户端发送的写操作就会在原主库上写入数据了。下图展示了脑裂的发生过程。

Redis 提供了两个配置项来限制主库的请求处理,分别是 min-slaves-to-write 和 min-slaves-max-lag。

这两个配置项组合后的要求是, 主库连接的从库中至少有 N 个从库,和主库进行数据复制时的 ACK 消息延迟不能超过 T 秒,否则,主库就不会再接收客户端的请求了 。

假设我们将 min-slaves-to-write 设置为 1,把 min-slaves-max-lag 设置为 12s,把哨兵的 down-after-milliseconds 设置为 10s,主库因为某些原因卡住了 15s,导致哨兵判断主库客观下线,开始进行主从切换。同时,因为原主库卡住了 15s,没有一个从库能和原主库在 12s 内进行数据复制,原主库也无法接收客户端请求了。这样一来,主从切换完成后,也只有新主库能接收请求,不会发生脑裂,也就不会发生数据丢失的问题了。

主从数据不一致,就谨正是指客户端从从库中读取到的值和主库中的最新值并不一致。举个例子,假设主从库之前保存的用户年龄值是 19,但是主库接收到了修改命令,已经把这个数据更新为 20 了,但是,从库中的值仍然是 19。那么,如果客户端从从库中读取用户年龄值,就会读到旧值。

出现主从数据不一致的主要原因是 主从库间的命令复制是异步进行的。 从库会滞后执行数据同步命令的原因主要有两个

应对主从数据不一致的解决方案:

我们可以开发一个监控程序,先用 INFO replication 命令查到主、从库的进度,然后,我们用 master_repl_offset 减去 slave_repl_offset,这样就能得到从库和主库间的复制进度差值了。 如果某个从库的进度祥塌悔差值大于我们预衫誉设的阈值,我们可以让客户端不再和这个从库连接进行数据读取,这样就可以减少读到不一致数据的情况 。不过,为了避免出现客户端和所有从库都不能连接的情况,我们需要把复制进度差值的阈值设置得大一些。可以周期性地运行这个流程来监测主从库间的不一致情况。

Redis 同时使用了两种策略来删除过期的数据,分别是 惰性删除策略和定期删除策略 。关于删除策略可以参考:

如果你使用的是 Redis 3.2 之前的版本,那么,从库在服务读请求时,并不会判断数据是否过期,而是会返回过期数据。在 3.2 版本后,Redis 做了改进,如果读取的数据已经过期了,从库虽然不会删除,但是会返回空值,这就避免了客户端读到过期数据。所以,在应用主从集群时, 尽量使用 Redis 3.2 及以上版本。

设置数据过期时间的命令一共有 4 个,我们可以把它们分成两类:

当主从库全量同步时,如果主库接收到了一条 EXPIRE 命令,那么,主库会直接执行这条命令。这条命令会在全量同步完成后,发给从库执行。而从库在执行时,就会在当前时间的基础上加上数据的存活时间,这样一来,从库上数据的过期时间就会比主库上延后了。

假设当前时间是 2021 年 5 月 5 日晚上 9 点,主从库正在同步,主库收到了一条命令:EXPIRE testkey 60,这就表示,testkey 的过期时间就是 5 日晚上 9 点 1 分,主库直接执行了这条命令。

但是,主从库全量同步花费了 2 分钟才完成。等从库开始执行这条命令时,时间已经是 9 点 2 分了。而 EXPIRE 命令是把 testkey 的过期时间设置为当前时间的 60s 后,也就是 9 点 3 分。如果客户端在 9 点 2 分 30 秒时在从库上读取 testkey,仍然可以读到 testkey 的值。但是,testkey 实际上已经过期了。

为了避免这种情况, 在业务应用中使用 EXPIREAT/PEXPIREAT 命令,把数据的过期时间设置为具体的时间点,避免读到过期数据。

每天一个知识点:Redis 主从库如何实现数据一致?

Redis 提供了主从库模式,以保证数据副本的一致,主从库之间采用的是读写分离的方式。

当我们启动多个 Redis 实例的时候,它们相互之间就可以通过 replicaof(Redis 5.0 之前使用 slaveof)命令形成主库和从库的关系,之后会按照三个阶段完成数据的第一次同步。

奥妙就在于 repl_backlog_buffer 这个缓冲区。当主从库断连后,主库会把断连期间收到的写操作命令,写入 replication buffer,同时也会把这些操作命令也写入 repl_backlog_buffer 这个缓冲区。repl_backlog_buffer 是一个环形缓冲区,主库会记录自己写到的位置,从库则会记录自己败迅已经读到的位置。刚开始的时候,主库和从库的写读位置在一起,这算是它们的起始位置。随着主库不断接收新的写操作,它在缓冲区中的写位置会逐步偏离起始位置,我们通常用偏移量来衡量这个偏移距离的大小,对主库来说,对应的偏移量就是 master_repl_offset。主库接收的新写操作越多,这个值就会越大。同样,从库在复制完写操作命令后,它在缓冲区中的读位置也开始逐步偏移刚才的起始位置,此时,从库已复制的偏移量 slave_repl_offset 也在不断增加。正常情况下,这两个偏移量基本相等。主从库的连接恢复之后,从库首先会给主库发送 psync 命令,并把自己当前的 slave_repl_offset 发给主库,主库会判断自己的 master_repl_offset 和 slave_repl_offset 之间的差距。在网络断连阶段,主库可能会收到新的写操作命令,所以,一般来说,master_repl_offset 会大于 slave_repl_offset。此时,主库只用把 master_repl_offset 和 slave_repl_offset 之间的命令操作同步给从库就行。需要注意的是,因为 repl_backlog_buffer 是一个环形缓冲区,所以在缓冲区写满后,主库会继续写入,此时,就会覆盖掉之前写世渣入的操作。如果从库的读取速度比较慢,就有可能导致从库还未读取的操作被主库新写的操作覆盖了,这会导致主从库间的数据不一致。要想办法避免这一情况,一般而言,我们可以调整 repl_backlog_size 这个参数。这个参数和所需的缓冲空间大小有关搜枯悄。缓冲空间的计算公式是:缓冲空间大小 = 主库写入命令速度 * 操作大小 - 主从库间网络传输命令速度 * 操作大小。在实际应用中,考虑到可能存在一些突发的请求压力,我们通常需要把这个缓冲空间扩大一倍,即 repl_backlog_size = 缓冲空间大小 * 2,这也就是 repl_backlog_size 的最终值。

关于redis主从同步和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

标签列表