Hello Redis,我有7个问题想请教你( 六 )

  • Master 发送从 Offset 偏移后的缓冲区数据给 Slave 。
  • Slave 获取数据更新自身数据 。
  • Redis 是怎么制定过期删除策略的
    当一个键处于过期的状态,其实在 Redis 中这个内存并不是实时就被从内存中进行摘除,而是 Redis 通过一定的机制去把一些处于过期键进行移除,进而达到内存的释放,那么当一个键处于过期,Redis 会在什么时候去删除?
    几时被删除存在三种可能性,这三种可能性也代表了 Redis 的三种不同的删除策略 。
    • 定时删除:在设置键过去的时间同时,创建一个定时器,让定时器在键过期时间来临,立即执行对键的删除操作 。
    • 惰性删除:放任键过期不管,但是每次从键空间获取键时,都会检查该键是否过期,如果过期的话,就删除该键 。
    • 定期删除:每隔一段时间,程序都要对数据库进行一次检查,删除里面的过期键,至于要删除多少过期键,由算法而定 。
    ①定时删除
    设置键的过期时间,创建定时器,一旦过期时间来临,就立即对键进行操作 。
    这种对内存是友好的,但是对 CPU 的时间是最不友好的,特别是在业务繁忙,过期键很多的时候,删除过期键这个操作就会占据很大一部分 CPU 的时间 。
    要知道 Redis 是单线程操作,在内存不紧张而 CPU 紧张的时候,将 CPU 的时间浪费在与业务无关的删除过期键上面,会对 Redis 的服务器的响应时间和吞吐量造成影响 。
    另外,创建一个定时器需要用到 Redis 服务器中的时间事件,而当前时间事件的实现方式是无序链表,时间复杂度为 O(n),让服务器大量创建定时器去实现定时删除策略,会产生较大的性能影响,所以,定时删除并不是一种好的删除策略 。
    ②惰性删除
    与定时删除相反,惰性删除策略对 CPU 来说是最友好的,程序只有在取出键的时候才会进行检查,是一种被动的过程 。
    与此同时,惰性删除对内存来说又是最不友好的,一个键过期,只要不再被取出,这个过期键就不会被删除,它占用的内存也不会被释放 。
    很明显,惰性删除也不是一个很好的策略,Redis 是非常依赖内存和较好内存的,如果一些长期键长期没有被访问,就会造成大量的内存垃圾,甚至会操成内存的泄漏 。
    在对执行数据写入时,通过 expireIfNeeded 函数对写入的 Key 进行过期判断 。
    其中 expireIfNeeded 在内部做了三件事情,分别是:
    • 查看 Key 是否过期 。
    • 向 Slave 节点传播执行过去 Key 的动作 。
    • 删除过期 Key 。
    ③定期删除
    上面两种删除策略,无论是定时删除和惰性删除,这两种删除方式在单一的使用上都存在明显的缺陷,要么占用太多 CPU 时间,要么浪费太多内存 。
    定期删除策略是前两种策略的一个整合和折中:
    • 定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时间和频率来减少删除操作对 CPU 时间的影响 。
    • 通过合理的删除执行的时长和频率,来达到合理的删除过期键 。
    总结
    Redis 可谓博大精深,简单的七连问只是盲人摸象,这次只是摸到了一根象鼻子,还应该顺着鼻子向下摸,下次可能摸到了一只象耳朵 。
    只要愿意往下深入去了解去摸索,而不只应用不思考,总有一天会把 Redis 这只大象给摸透了 。
    作者:陈于喆,注:部分章节参考和引用黄健宏 《Redis 设计与实现》
    简介:十余年的开发和架构经验,国内较早一批微服务开发实施者 。曾任职国内互联网公司网易和唯品会高级研发工程师,后在创业公司担任技术总监/架构师,目前在洋葱集团任职技术研发副总监 。负责技术部门研发体系建设,团建建设,人才培养,推动整个技术架构演进以及升级,带领技术团队构建微服务架构体系、平台架构体系、自动化运维体系 。
    陈于喆来源:51CTO技术栈




    推荐阅读