redis读写分离问题

问题:redis读写分离的时候,从库中读取到了已经过期的key,假如没有主库操作过该key,则从库中的key在很长时间之后才删除掉

解决办法:将redis的版本升为3.2以上;

在redis 3.2-rc1版本中,redis加入了一个新特性来解决主从不一致导致读取到过期数据的问题(好吧,虽然这个新特性我们一直觉得是个bug fix),在源码db.c文件中,作者对lookupKeyRead(读命令)做了相应的修改,增加了key是否过期以及对主从库的判断(代码如下),如果key已过期,当前访问的是master则返回null;当前访问的是从库,且执行的是只读命令也返回null(老版本从库真实的返回该操作的结果,如果该key过期后主库没有删除),源码片段如下:

redis读写分离问题_第1张图片

原因分析:

redis的过期策略采用: 惰性清理与定时清理结合;

redis的清理过期的key的策略:

1、惰性清理:当读/写一个过期的key时触发

2、定时清理:定期巡检,删除过期的key;hz 10 :每秒执行10次activeExpireCycle 函数

3、当内存达到maxmemory配置时候,会触发Key的删除操作;(当达到最大内存时,也可以配置其他策略保证内存不会超出)

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

源码中的server.masterhost,只有从库的时候才有值非null,主库的时候是null;

1、惰性清理,

redis 源码中 lookupKeyRead,lookupKeyWrite,dbRandomKey,existsCommand,keysCommand 调用 expireIfNeeded,(通过这些函数命名可以看出,只要访问了某一个key,顺带做的事情就是尝试查看过期并删除,这就保证了用户不可能访问到过期的key)

if (server.masterhost != NULL) return now > when; 如果是从库,就return了,redis的从库不会执行惰性清理;

redis读写分离问题_第2张图片

2、定时清理

 

redis的定时任务,通过serverCron执行;它主要执行下列操作:

  • 更新服务器的各类统计信息,比如时间、内存占用、数据库占用情况等
  • 清理数据库中的过期键值对 使用的函数:activeExpireCycle
  • 对不合理的数据库进行大小调整
  • 关闭和清理连接失效的客户端
  • 尝试进行 AOF 或 RDB 持久化操作
  • 如果服务器是主节点的话,对附属节点进行定期同步
  • 如果处于集群模式的话,对集群进行定期同步和连接测试

一般情况下serverCron没秒执行10次,redis.config的hz可以配置;采用默认值即可。

redis读写分离问题_第3张图片

 

在server.c中调用activeExpireCycle函数的记录中可以看出,只有是主库的时候才会进行定时清理;

定时清理:server.c activeExpireCycle(type) 来完成; type用来区分是快速模式,还是正常模式;

正常模式:执行时间限制25ms

快速模式:执行时间限制1ms

随机抽样带有过期时间的key(好像是100个),如果有25%的key已经过期(判断到过期后会删除),则会再次抽样,依次循环调用,;大体的流程是这样的,如果,主库中大部分的key都是未过期的,那一秒中最多10次抽样,如果key足够多,那理论上半个小时或几个小时后才会抽样抽到该未过期的key。

 

参考:https://blog.csdn.net/u012538947/article/details/52540313

https://github.com/antirez/redis/issues/1768

http://www.cnblogs.com/bridger/archive/2012/11/07/2758734.html

http://www.tuicool.com/articles/INRZFr

redis读写分离问题_第4张图片

你可能感兴趣的:(数据库)