Loading

redis过期策略?以及过期的实现关键点?

redis的key有个有效期限,这个应该都知道,如果你不知道,说明你基础很差。
比如我们有个key,我们只给了他五分钟的有效期,五分钟过后,这个key就算是失效了。那么,在redis中,一个key过期实际上是有三种策略来对待的,并不是一定是过期就立马删除。

下面先说三种比较常见的删除策略,这些策略都是通用:

  • 定时删除。在设置了key的过期时间后,同时创建一个定时器当看门狗,随时盯着这个key是不是已经到了,到期后立马ko掉。这种方式有一个好处就是可以及时释放内存,坏处是需要大量的定时器,而且如果很不巧很多key都在几乎同一个时间点删除,那么这一刻redis的压力会很大。

  • 定期删除。这个比较容易理解,就是隔一段时间就启动一次扫描,当然是针对过期key的,其余不受影响。当然了,这么做有一个缺点就是可能导致内存释放并不及时。

  • 惰性删除。这是最懒惰的方法了,确切说来就是key过期了也不删除,而是这个key被操作的时候才会去判断是不是过期了,如果过期了就KO掉同时还得告诉客户端,没有这个key。这么做有一个好处就是CPU压力会小很大,不会有太多频繁的定时器调度以及集中批量key的删除操作,但是最大的坏处就是对内存占用比较浪费。

其中可以看出来前两种操作属于主动进取型的策略,而第三种属于被动偷懒型的策略。各有利弊,没有十全十美的。那么redis采用的是哪种呢?

redis采用的是 惰性删除 + 定期删除 两种策略,用来保证对内存利用最佳。惰性删除就不说了,主要是定期删除。每当启动后,redis会依次遍历所有的16(默认情况)个库,然后随机从中挑选20个具有过期时间的key,然后看看这些key是不是已经过期,如果过期就ko掉,除此之外,还要查看本次定期删除操作是否已经超过了执行时间,因为redis还定义了每次定期删除操作的操作时间有多长,不能一直执行下去。

那么,redis内部是如何实现定时操作的呢?主要是redisDb这个结构体,如下:

typedef struct redisDb {
  dict *dict;
  dict *expires;
  ......
}

注意看expires这个指针变量,它指向的是一个dict,其实指向哈希的成员属性,这个指针指向的地方存储的是设置了过期时间的key,那么实际上redis的两种过期策略的操作都是针对这个dict来进行的。这就是关键实现处!至于删除逻辑,实际上就是上述两种删除策略,你们甚至可以用php来模仿实现两种删除策略!

 

转: https://ti-node.com/

posted @ 2018-09-10 10:40  王召波  阅读(889)  评论(0编辑  收藏  举报