redis是一个高性能的内存数据库,它可以存储各种类型的数据,如字符串、列表、集合、散列等。redis的优点是速度快、支持多种数据结构、具有丰富的功能和扩展性。但是,redis也有一个缺点,就是它占用的内存空间会随着数据量的增加而增加,如果不加以控制,可能会导致内存溢出或性能下降。
为了解决这个问题,redis提供了一种定时清除功能,它可以根据一定的规则,定期删除一些不需要的或过期的数据,从而释放内存空间。这种功能叫做过期键删除(expire keys deletion)。redis有两种过期键删除的方式,一种是惰性删除(lazy deletion),另一种是定时删除(timed deletion)。
惰性删除是指当一个键被访问时,redis会检查它是否已经过期,如果是,就删除它。这种方式的好处是节省CPU资源,只有当键被访问时才进行删除操作。但是,这种方式也有一个缺点,就是如果有很多键没有被访问,但是已经过期,它们就会一直占用内存空间,造成内存浪费。
定时删除是指redis会定期扫描数据库中的所有键,找出已经过期的键,并删除它们。这种方式的好处是可以及时释放内存空间,避免内存浪费。但是,这种方式也有一个缺点,就是扫描数据库会消耗CPU资源,如果扫描频率太高或者数据库太大,可能会影响redis的性能。
为了平衡惰性删除和定时删除的优缺点,redis采用了一种折中的策略,叫做定期删除(periodic deletion)。定期删除是指redis会每隔一段时间(默认为1秒),随机选择一些数据库,并在每个数据库中随机选择一些键(默认为20个),检查它们是否已经过期,并删除过期的键。这种方式可以减少扫描数据库的次数和范围,同时也可以保证过期键能够被及时删除。
那么,redis为什么要在每天凌晨执行清除操作呢?这其实是基于一个假设,就是在每天凌晨时段,redis的访问量会比较低,因此可以利用这个时间段来进行更彻底的清除操作。具体来说,redis会在每天凌晨执行以下两个操作:
1.主动过期键删除(active expire keys deletion)。这个操作类似于定时删除,但是更加强力。它会在每个数据库中扫描所有的键,并删除所有已经过期的键。这个操作可以保证在每天凌晨之后,数据库中没有任何过期的键。
2.碎片整理(defragmentation)。这个操作是针对redis使用的内存分配器(jemalloc)而言的。由于redis频繁地分配和释放内存空间,可能会导致内存空间出现碎片(fragmentation),即有很多小块的空闲内存,但是无法被合并或利用。这个操作会对内存空间进行整理,将碎片合并或释放,从而提高内存的利用率。
通过在每天凌晨执行清除操作,redis可以有效地优化数据库的性能,提高内存的利用率,避免内存溢出或性能下降。如果你想使用这个功能,你只需要在redis的配置文件中设置以下参数:
1.active-expire-effort。这个参数用来控制主动过期键删除的强度,取值范围是1到10,默认为1。数值越大,表示扫描数据库的次数和范围越大,删除过期键的效果越好,但是也会消耗更多的CPU资源。你可以根据你的数据库大小和访问量来调整这个参数。
2.active-defrag-threshold-lower和active-defrag-threshold-upper。这两个参数用来控制碎片整理的触发条件,分别表示内存碎片率的下限和上限,默认为10%和100%。当内存碎片率超过上限时,碎片整理会开始执行。