深入理解Redis主键失效原理及实现机制
作为一种定期清理无效数据的重要机制,主键失效存在于大多数缓存系统中,Reids也不例外。在Redis提供的诸多命令中,EXPIRE、EXPIREAT、PEXPIRE、PEXPIREAT以及SETEX和PSETEX均可以用来设置一条Key-Value对的失效时间,而一条Key-Value对一旦被关联了失效时间就会在到期后自动删除(或者说变得无法访问更为准确)。可以说,主键失效这个概念还是比较容易理解的,但是在具体实现到Redis中又是如何呢?最近本博主就对Redis中的主键失效机制产生了几个疑问,并根据这些疑问对其进行了仔细的探究,现总结所得如下,以飨各位看客。
代码段一:
代码段二:
代码段三:
以上我们通过对expireIfNeeded函数的介绍了解了Redis是如何以一种消极的方式删除失效主键的,但是仅仅通过这种方式显然是不够的,因为如果某些失效的主键迟迟等不到再次访问的话,Redis就永远不会知道这些主键已经失效,也就永远也不会删除它们了,这无疑会导致内存空间的浪费。因此,Redis还准备了一招积极的删除方法,该方法利用Redis的时间事件来实现,即每隔一段时间就中断一下完成一些指定操作,其中就包括检查并删除失效主键。这里我们说的时间事件的回调函数就是serverCron,它在Redis服务器启动时创建,每秒的执行次数由宏定义REDIS_DEFAULT_HZ来指定,默认每秒钟执行10次。代码段四给出该时间事件创建时的程序代码,该代码在redis.c文件的initServer函数中。实际上,serverCron这个回调函数不仅要进行失效主键的检查与删除,还要进行统计信息的更新、客户端连接超时的控制、BGSAVE和AOF的触发等等,这里我们仅关注删除失效主键的实现,也就是函数activeExpireCycle。
if(aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {
代码段五给出了函数activeExpireCycle的实现及其详细描述,其主要实现原理就是遍历处理Redis服务器中每个数据库的expires字典表中,从中尝试着随机抽样REDIS_EXPIRELOOKUPS_PER_CRON(默认值为10)个设置了失效时间的主键,检查它们是否已经失效并删除掉失效的主键,如果失效的主键个数占本次抽样个数的比例超过25%,Redis会认为当前数据库中的失效主键依然很多,所以它会继续进行下一轮的随机抽样和删除,直到刚才的比例低于25%才停止对当前数据库的处理,转向下一个数据库。这里我们需要注意的是,activeExpireCycle函数不会试图一次性处理Redis中的所有数据库,而是最多只处理REDIS_DBCRON_DBS_PER_CALL(默认值为16),此外activeExpireCycle函数还有处理时间上的限制,不是想执行多久就执行多久,凡此种种都只有一个目的,那就是避免失效主键删除占用过多的CPU资源。代码段五有对activeExpireCycle所有代码的详细描述,从中可以了解该函数的具体实现方法。
代码段五:
三、Memcached删除失效主键的方法与Redis有何异同?首先,Memcached在删除失效主键时也是采用的消极方法,即Memcached内部也不会监视主键是否失效,而是在通过Get访问主键时才会检查其是否已经失效。其次,Memcached与Redis在主键失效机制上的最大不同是,Memcached不会像Redis那样真正地去删除失效的主键,而只是简单地将失效主键占用的空间回收。这样当有新的数据写入到系统中时,Memcached会优先使用那些失效主键的空间。如果失效主键的空间用光了,Memcached还可以通过LRU机制来回收那些长期得不到访问的空间,因此Memcached并不需要像Redis中那样的周期性删除操作,这也是由Memcached使用的内存管理机制决定的。同时,这里需要指出的是Redis在出现OOM时同样可以通过配置maxmemory-policy这个参数来决定是否采用LRU机制来回收内存空间(感谢@Jonathan_Dai同学在博文http://xenojoshua.com/2013/07/redis-lru/中对原文的指正)!
四、Redis的主键失效机制会不会影响系统性能?通过以上对Redis主键失效机制的介绍,我们知道虽然Redis会定期地检查设置了失效时间的主键并删除已经失效的主键,但是通过对每次处理数据库个数的限制、activeExpireCycle函数在一秒钟内执行次数的限制、分配给activeExpireCycle函数CPU时间的限制、继续删除主键的失效主键数百分比的限制,Redis已经大大降低了主键失效机制对系统整体性能的影响,但是如果在实际应用中出现大量主键在短时间内同时失效的情况还是会使得系统的响应能力降低,所以这种情况无疑应该避免。
参考文献链接:http://redis.io/commands/expire
相关文章
- 谁还敢“偷”我的脸?杭州、深圳等多地发布人脸识别新规
- 不「偷窥」用户对话也能精准投放广告?Facebook研发同态加密技术
- python django项目配置及启动
- 【Kaggle】Telco Customer Churn 电信用户流失预测案例 ----数据预处理
- 【0基础学爬虫】爬虫基础之爬虫的基本介绍
- anaconda peompt 、labalimg 数据标注
- odoo关于计算字段store=True时导致的安装/更新时间较长问题的解决方案
- 分享Python7个爬虫小案例(附源码)
- 计算机介绍和五大组成
- MP 代码生成器工具类
- 【建议收藏】超详细的Canal入门,看这篇就够了!!!
- 排查系统执行SQL与数据库直接执行结果不一致的问题
- 网络通信——TCP “三次握手“、“四次挥手“ 详解
- JDBC 连接 MySQL
- 序列类型
- 面试官:从 MySQL 读取 100w 数据进行处理,应该怎么做?问倒一大遍!
- 理论+实战,详解Sharding Sphere-jdbc
- 宕机了,Redis 如何避免数据丢失?
- 通过手动创建hibernate工厂,自动生成表,完成数据库备份还原功能
- es6新增哪些特性