* See issue #1525 on Github for more information. */
now = server.lua_caller ? server.lua_time_start : mstime();
/* If we are running in the context of a slave, return ASAP:
* the slave key expiration is controlled by the master that will
* send us synthesized DEL operations for expired keys.
*
* Still we try to return the right information to the caller,
* that is, 0 if we think the key should be still valid, 1 if
* we think the key is expired at this time. */
/*如果我们正在slaves上执行读写命令,就直接返回,
*因为slaves上的过期是由master来发送删除命令同步给slaves删除的,
*slaves不会自主删除*/
if (server.masterhost != NULL) return now > when;
/*只是回了一个判断键是否过期的值,0表示没有过期,1表示过期
*但是并没有做其他与键值过期相关的操作*/
/* Return when this key has not expired */
/*如果没有过期,就返回当前键*/
if (now <= when) return 0;
/* Delete the key */
/*增加过期键个数*/
server.stat_expiredkeys++;
/*传播键过期的消息*/
propagateExpire(db,key);
notifyKeyspaceEvent(REDIS_NOTIFY_EXPIRED,"expired",key,db->id);
/*删除过期键*/
return dbDelete(db,key);
}
以上是expireIfNeeded函数的源码,源码中的注释已经很清楚的描述出了它的逻辑,我只是将他翻译成中文,然后加了一点自己的注释。值得注意的如果是slaves,它是不能自主删除键的,需要由master发del命令,然后同步到所有的slaves,这样就不会造成主从数据不一致的问题。
(4)策略总述:
懒惰淘汰机制和定时淘汰机制是一起合作的,就好像你开一家餐馆一样,定时淘汰机制就是你每隔几小时去查看所有的菜品是否还有,如果有的菜品现在卖光了,就将他从菜单上划掉。懒惰淘汰机制就是有客人要点宫保鸡丁,你马上去查看还有没有,如果今天的已经卖完了,就告诉客人不好意思,我们卖完了,然后将宫保鸡丁从菜单上划掉。只有等下次有原料再做的时候,才又把它放到菜单上去。
所以,在实际中,如果我们要自己设计过期策略,在使用懒汉式删除+定期删除时,控制时长和频率这个尤为关键,需要结合服务器性能,已经并发量等情况进行调整,以致最佳。
三、对开发需求而言,Redis过期策略的设计实现经验
(1)分析缓存键值的客户方角度,调和服务器内存压力
基于服务器内存是有限的,但是缓存是必须的,所以我们就要结合起来选择一个平衡点。所以一般来说,我们采取高访问量缓存策略—就是给那些经常被访问的数据,维持它较长的key生存周期。
(2)估算过期时间
这个就要结合我们自己的业务去估量了。
参考因素:数据的访问量、并发量,数据的变化更新的时间,服务器数据内存大小……
(3)Java演示一策略做法。
每次访问刷新对应key生存时间:
针对经常访问的数据的策略
//加进redis时,设置生存时间
@Override
public String set(String key, String value) {
Jedis jedis = jedisPool.getResource();
String string = jedis.set(key, value);
jedis.expire(key,5);
System.out.println("key : "+key);
System.out.println("查看key的剩余生存时间:"+jedis.ttl(key));
jedis.close();
return string;
}
//从redis获取时
@Override
public String get(String key) {
Jedis jedis = jedisPool.getResource();
String string = jedis.get(key);
jedis.expire(key,5);//每次访问刷新时间
jedis.close();
return string;
}
讲到这就结束了,大家有什么不同的见解或意见可以给我留言噢,欢迎大家评论!
閱讀更多 互聯網Java架構 的文章