运维开发网

Redis主从之从Redis服务器Key不失效

运维开发网 https://www.qedev.com 2020-05-21 12:58 出处:网络 作者:运维开发网整理
大家在使用redis的时候,经常会用expire来设置key的过期时间,以为某个key到期就会马上清除。如果只是在单个redis(即一个主redis)下是没有问题的。但是如果为了实现读写分离,搭建了主从服务器,那么就会遇上从库Key不失效的问题了。(使用Redis3.2以后版本的同学请忽略,3.2之后的版本已不存在以下问题) 场景重现: [java]  view plain  copy 主: se

大家在使用redis的时候,经常会用expire来设置key的过期时间,以为某个key到期就会马上清除。如果只是在单个redis(即一个主redis)下是没有问题的。但是如果为了实现读写分离,搭建了主从服务器,那么就会遇上从库Key不失效的问题了。(使用Redis3.2以后版本的同学请忽略,3.2之后的版本已不存在以下问题)

场景重现:

[java]  view plain  copy
  1. 主: setex name 20 Johny  
  2.   
  3. 从:  
  4.   
  5. get name >> Johny  
  6.   
  7. ttl name >> 18  
  8.   
  9. // 过了一分钟...  
  10.   
  11. // 发现name这个key已经失效了     
  12. ttl name >> -1  
  13.   
  14. get name >> Johny  // 仍然能获取到key的值   
  15.   
  16. 主:get  name >> nil // 主Redis服务器上获取不到  
  17.   
  18. 从:get name >> nil // 此时,从Redis服务器上也获取不到了    

Redis key的三种过期策略

  1. 惰性删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key,很明显,这是被动的!

  2. 定期删除:由于惰性删除策略无法保证冷数据被及时删掉,所以 redis 会定期主动淘汰一批已过期的key。(在第二节中会具体说明)

  3. 主动删除:当前已用内存超过maxMemory限定时,触发主动清理策略。主动设置的前提是设置了maxMemory的值

Redis删除过期Key的源码 [cpp]  view plain  copy
  1. int expireIfNeeded(redisDb *db, robj *key) {  
  2.     time_t when = getExpire(db,key);  
  3.   
  4.     if (when < 0) return 0; /* No expire for this key */  
  5.   
  6.     /* Don't expire anything while loading. It will be done later. */  
  7.     if (server.loading) return 0;  
  8.   
  9.     /* If we are running in the context of a slave, return ASAP: 
  10.      * the slave key expiration is controlled by the master that will 
  11.      * send us synthesized DEL operations for expired keys. 
  12.      * 
  13.      * Still we try to return the right information to the caller,  
  14.      * that is, 0 if we think the key should be still valid, 1 if 
  15.      * we think the key is expired at this time. */  
  16.     if (server.masterhost != NULL) {  
  17.         return time(NULL) > when;  
  18.     }  
  19.   
  20.     /* Return when this key has not expired */  
  21.     if (time(NULL) <= when) return 0;  
  22.   
  23.     /* Delete the key */  
  24.     server.stat_expiredkeys++;  
  25.     propagateExpire(db,key);  
  26.     return dbDelete(db,key);  
  27. }  
通过以上源码发现,4行:没有设置超时时间,则不删;7行:在"loading"时不删; 16行:非主库不删;21行未到期不删。25行同步从库和文件。

所以说,在从库执行主动删除操作,或者通过惰性删除的方式触发删除key的操作,最终都不会执行成功。原因就在上面的第16行代码。 参考:https://github.com/antirez/redis/issues/1768    http://www.cnblogs.com/bridger/archive/2012/11/07/2758734.html

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

转载于:https://blog.csdn.net/u012538947/article/details/52540313

0

精彩评论

暂无评论...
验证码 换一张
取 消