如何制定Redis过期策略

* 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;

}

讲到这就结束了,大家有什么不同的见解或意见可以给我留言噢,欢迎大家评论!


分享到:


相關文章: