redis面试:由于主从延迟导致读取到过期数据怎么处理

读写分离,当使用从节点响应读请求时,业务端可能会遇到如下问题:

  • 复制数据延迟
  • 读到过期数据
  • 从节点故障

复制数据延迟

因为主从库间的命令复制是异步进行的,所以有可能客户端从从客户读取到的主和主库中最新值不一致。

具体来说,在主从库命令传播阶段,主库收到新的写命令后,会发生给从库。但是,主库并不会等到从库实际执行完命令后,再把结果返回给客户端。如果从库还没有执行主库同步过来的命令,主从库键的数据就不会一致了。

从库滞后执行同步命令主要有两种情况

  • 一方面,主从库间的网络可能会有传输延迟,所以从库不能及时收到主库发送的命令,从库上执行同步命令的时间就会被延后
  • 另一方面,及时从库及时收到了主库的命令,但是,也可能会因为正在处理其他复杂度高的命令而阻塞

为了避免从库会滞后执行同步命令,方法如下:

  • 首先,在硬件配置方面,我们要尽量保证主从库间的网络连接良好。比如,我们要避免把主从库部署在不同机房,或者是避免把网络通信密集的应用(比如数据分析应用)和redis主从库部署在一起。
  • 另外,在主节点写入数据后立即在从节点上读取可能获取不到(由于网络带宽和命令阻塞),因此需要业务场景允许短时间内的数据延迟
  • 如果无法容忍大量延迟场景,可以编写外部监听程序监听主从节点的复制偏移量,当延迟较大时触发报警或者通知客户端避免读取延迟过高的从节点。实现逻辑如下:
    • 监控程序(monitor)定期检查主从节点的偏移量,主节点偏移量在info replication的master_repl_offset指标记录,从节点偏移量可以查询主节点的slave0字段的offset指标,它们的差值就是主从节点延迟的字节量
    • 当延迟字节量过高时,比如超过10MB。监控程序触发报警并通知客户端从节点延迟过高。可以采用Zookeeper的监听回调机制实现客户端通知
    • 客户端接到具体的从节点高延迟通知后,修改读命令路由到其他从节点或者主节点上。当延迟恢复后,再次通知客户端,恢复从基地的读命令请求
    • 这种方案的成本比较高,需要单独修改适配Redis的客户端类库。如果涉及多种语言成本将会扩大。客户端逻辑需要识别出读写请求并自动路由, 还需要维护故障和恢复的通知。采用此方案视具体的业务而定,如果允许不 一致性或对延迟不敏感的业务可以忽略,也可以采用Redis集群方案做水平扩展

读到过期数据

redis的从库是无法主动的删除已经过期的key的,所以如果做了读写分离,就很有可能在从库读到脏数据

当主节点存储大量设置超时的数据时,如缓存数据,Redis内部需要维护过期数据删除策略。删除策略主要有两种:惰性删除和定时删除。

  • 惰性删除:主节点每次处理读取命令时,都会检查键是否超时,如果超时则执行del命令删除键对象,之后del命令也会异步发送给从节点。需要注意的是为了保证复制的一致性,从节点自身永远不会主动删除超时数据

在这里插入图片描述

  • 定时删除:Redis主节点在内部定时任务会循环采样一定数量的键,当发现采样的键过期时执行del命令,之后再同步给从节点,如下图所示
    在这里插入图片描述
    如果此时数据大量超时,主节点采样速度跟不上过期速度而且主节点没有读取过期键的操作,那么从节点将无法收到del命令。此时在从节点上就可以读取到已经超时的数据。

如何避免从库读取到脏数据

  1. 通过scan命令扫库

当redis中的key被scan时,相当于访问了该key,同样也会做过期检测,充分发挥redis惰性删除的策略。这个方法能大大降低脏数据读取的概念。缺点也比较明显,会造成一定的数据压力。

  1. 升级到redis新版本

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

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。 Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。 Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。   本课程主要讲解以下内容:1. Redis的基本使用2. Redis数据库的数据类型3. Redis数据库数据管理4. Redis主从复制5. Redis数据库的持久性6. Redis的高可靠性和集群7. Redis的优化和性能测试8. Redis服务器的维护和管理9. Redis服务器的常见问题排错 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值