• Kaito
    2020-11-02
    把 slave-read-only 设置为 no,让从库也能直接删除数据,以此来避免读到过期数据,这种方案是否可行? 我个人觉得这个问题有些歧义,因为尽管把 slave-read-only 设置为 no,其实 slave 也不会主动过期删除从 master 同步过来的数据的。 我猜老师想问的应该是:假设让 slave 也可以自动删除过期数据,是否可以保证主从库的一致性? 其实这样也无法保证,例如以下场景: 1、主从同步存在网络延迟。例如 master 先执行 SET key 1 10,这个 key 同步到了 slave,此时 key 在主从库都是 10s 后过期,之后这个 key 还剩 1s 过期时,master 又执行了 expire key 60,重设这个 key 的过期时间。但 expire 命令向 slave 同步时,发生了网络延迟并且超过了 1s,如果 slave 可以自动删除过期 key,那么这个 key 正好达到过期时间,就会被 slave 删除了,之后 slave 再收到 expire 命令时,执行会失败。最后的结果是这个 key 在 slave 上丢失了,主从库发生了不一致。 2、主从机器时钟不一致。同样 master 执行 SET key 1 10,然后把这个 key 同步到 slave,但是此时 slave 机器时钟如果发生跳跃,优先把这个 key 过期删除了,也会发生上面说的不一致问题。 所以 Redis 为了保证主从同步的一致性,不会让 slave 自动删除过期 key,而只在 master 删除过期 key,之后 master 会向 slave 发送一个 DEL,slave 再把这个 key 删除掉,这种方式可以解决主从网络延迟和机器时钟不一致带来的影响。 再解释一下 slave-read-only 的作用,它主要用来控制 slave 是否可写,但是否主动删除过期 key,根据 Redis 版本不同,执行逻辑也不同。 1、如果版本低于 Redis 4.0,slave-read-only 设置为 no,此时 slave 允许写入数据,但如果 key 设置了过期时间,那么这个 key 过期后,虽然在 slave 上查询不到了,但并不会在内存中删除,这些过期 key 会一直占着 Redis 内存无法释放。 2、Redis 4.0 版本解决了上述问题,在 slave 写入带过期时间的 key,slave 会记下这些 key,并且在后台定时检测这些 key 是否已过期,过期后从内存中删除。 但是请注意,这 2 种情况,slave 都不会主动删除由 *master 同步过来带有过期时间的 key*。也就是 master 带有过期时间的 key,什么时候删除由 master 自己维护,slave 不会介入。如果 slave 设置了 slave-read-only = no,而且是 4.0+ 版本,slave 也只维护直接向自己写入 的带有过期的 key,过期时只删除这些 key。 另外,我还能想到的主从同步的 2 个问题: 1、主从库设置的 maxmemory 不同,如果 slave 比 master 小,那么 slave 内存就会优先达到 maxmemroy,然后开始淘汰数据,此时主从库也会产生不一致。 2、如果主从同步的 client-output-buffer-limit 设置过小,并且 master 数据量很大,主从全量同步时可能会导致 buffer 溢出,溢出后主从全量同步就会失败。如果主从集群配置了哨兵,那么哨兵会让 slave 继续向 master 发起全量同步请求,然后 buffer 又溢出同步失败,如此反复,会形成复制风暴,这会浪费 master 大量的 CPU、内存、带宽资源,也会让 master 产生阻塞的风险。
    展开

    作者回复: 感谢Kaito同学的回复和详细分析!很赞! 我也解释下,到时出这道题的一个考虑出发点。 这道题我其实是想问大家,假设从库也能直接删除过期数据的话,是不是一个好方法。其实,是想提醒下同学们,主从复制中的增删改都需要在主库执行,即使从库能做删除,也不要在从库删除。否则会造成数据不一致。例如,假设主从库上都能做写操作的话,主从库上有a:stock的键,客户端A给主库发送一个SET命令,修改a:stock的值,客户端B给从库发送了一个SET命令,也修改a:stock的值,此时,相同键的值就不一样了。所以,让从库可以做写操作会造成主从数据不一致。

    共 10 条评论
    213
  • 老大不小
    2021-04-28
    老师,slave-serve-stale-data这个命令说的不清不楚的,对于初学者来说不明就里。 slave-serve-stale-data 解释:当一个slave与master失去联系时,或者复制正在进行的时候,slave应对请求的行为:1) 如果为 yes(默认值) ,slave 仍然会应答客户端请求,但返回的数据可能是过时,或者数据可能是空的在第一次同步的时候;2) 如果为 no ,在你执行除了 info 和 salveof 之外的其他命令时,slave 都将返回一个 "SYNC with master in progress" 的错误。 29、slave-read-only 解释:设置slave是否是只读的。从2.6版起,slave默认是只读的。
    共 2 条评论
    26
  • 思变
    2020-11-04
    老师您好,关于bind参数,不是设置redis能接受哪个本机网卡接入的连接吗?为什么要配置多个哨兵的IP呢
    共 2 条评论
    6
  • 杨逸林
    2020-11-02
    不是个好方法,如果不同客户端,去非当前从库读取数据时,就会出现缓存不一致的情况。
    
    6
  • 小白白不白
    2021-03-05
    EXPIRE、PEXPIRE和EXPIREAT三个命令都会转换成PEXPIREAT命令来执行,难道redis对于aof日志文件没有转为PEXPIREAT吗?
    共 3 条评论
    5
  • 赵茭茭
    2020-12-07
    主从复制 不是复制的是rdb吗 不是aof啊 这个和指令 带AT的还有效吗 还是我理解的有问题
    共 1 条评论
    3
  • 刘浩
    2020-11-13
    slave-serve-stale-data配置了主从中断后,从库的逻辑 --no :从库只能应答INFO和SLAVEOF --yes默认 :正常应答 这样不知道对不对
    
    3
  • yu
    2021-03-28
    redis为何不把底层的expire实现成为expireAt,再发给从库进行同步,避免出现过期数据问题?
    共 2 条评论
    2
  • 零点999
    2020-11-02
    只有主库提供服务,从库只保证高可用
    
    2
  • Geek1254
    2021-06-20
    为什么不在主库删除过期key时给从库发送删除命令
    
    1