5分钟学会这种更高效的Redis数据删除方式

栏目: IT技术 · 发布时间: 6年前

1

| 作者: 冯伟源,腾讯云数据库架构师,腾讯云 Redis 从零到一的技术运营负责人,第九届中国数据库技术大会分享嘉宾,拥有八年数据库的运营开发与海量运维经验,曾让QQ与Qzone数据库业务达到一人万台服务器的运营成熟度。

1

我们知道,Del命令能删除数据,除此之外,数据在Redis中,还会以哪种方式被删除呢? 在Redis内存满一定会返回OOM错误? Key到达过期时间就立即删除? 删除大Key会影响性能吗? 下面,咱们一起探讨。

1

同步和异步删除

1.DEL 和 UNLINK

Redis服务自身对Key的删除,可以分为「同步删除」和「异步删除」。使用DEL命令会触发「同步删除」,如果Key是一个有很多元素的复杂类型,这个过程可能会堵塞一下Redis服务自身,从而影响用户的访问。如果使用UNLINK命令,Redis服务会先计算删除Key的成本,从而更智能地做出「同步删除」或「异步删除」的选择。注意,只有4.0版本后,才有UNLINK命令。

2.成本计算

那么,成本是如何计算的呢?对于list,hash,set,zset的对象类型,如果长度大于64(由宏LAZYFREE_THRESHOLD定义),才会采用异步删除的手段,从当前db先释放该key,再由另外一个线程做异步删除。对于长度不大于64的复杂类型,异步删除比同步删除还多了一些函数调用与多线程同步的代价,所以同步删除更好。对于string对象,底层的数据结构sds是一份连续的内存,内存分配器回收这块内存的复杂度是O(1),所以采用同步删除也不会堵塞服务。

总的来说,我们作为用户,都能用UNLINK替代DEL。

1

Key的驱逐

1.定义

Redis处理命令前根据内存容量是否触达上限而进行的Key驱逐。

2.驱逐策略

Redis通过参数maxmemory来选择不同的驱逐策略:

  • volatile-random 从已设置过期时间的数据集(server.db[i].expires)中任意选择数据驱逐;

  • volatile-lru 从数据集(server.db[i].dict)中挑选最近最少使用的数据驱逐(2.8默认);

  • volatile-ttl 从已设置过期时间的数据集(server.db[i].expires)中寻找最近即将过期(ttl最小)的key来驱逐;

  • allkeys-random 从数据集(server.db[i].dict)中任意选择数据驱逐;

  • allkeys-lru 从数据集(server.db[i].dict)中挑选最近最少使用的数据驱逐;

  • noeviction 禁止驱逐数据,永远不驱逐,仅对写操作返回一个错误(4.0默认);

在4.0版本后,还增加了以下两种驱逐策略。

  • volatile-lfu在过期集合中使用LFU链来驱逐数据;

  • allkeys-lfu 从数据集(server.db[i].dict)使用LFU算法来驱逐数据;

3.简述

Redis在处理命令前,会看看容量是否触达上限。

如果驱逐策略为noeviction,则不会驱逐Key,而是返回写失败。4.0后,在返回写入失败前,还会先检测lazyfree线程是否还有待删除的Key,没有才会给用户返回写入失败。

对于其他策略,都会根据相应定义,进行Key的驱逐,这里不再详述。

在4.0或以上的版本,Key的驱逐会基于参数lazyfree_lazy_eviction,来决定采用unlink还是del。在2.8版本,则只会用del。lazyfree_lazy_eviction参数在Qcloud 4.0上是no。

这里试问,主从节点都会进行「驱逐」么?

答案是都会的,各自会因应自身的驱逐策略进行驱逐,并且Master节点驱逐的删除命令还会传播到Slave节点。

1

Key的访问淘汰

1.定义

访问一个已过期的Key会触发对其的删除。

2.简述

与Key的驱逐一样,Key的访问淘汰同样是基于访问事件来触发的。

主从角色的节点在处理访问淘汰上的逻辑是不同的。

对于Slave节点,访问到了已过期的Key,Slave节点会返回该Key不存在,但不会主动删除该Key。删除的动作,还是会从Master上同步过来。

对于Master节点,在4.0或以上的版本,会根据参数lazyfree-lazy-expire,来决定用DEL还是UNLINK。对于2.8版本,则只能用DEL了。这些删除的动作,都会同步到Slave与AOF文件中。

在Qcloud 4.0以上的版本,默认是开启异步删除的,即lazyfree-lazy-expire=yes

1

Key的定时淘汰

1.定义

Redis自身的定时调度把已过期Key删除。

2.简述

多久会执行一次定时调度呢?

redis服务的参数hz能控制定时淘汰的频率,hz默认是10,即每秒能调度100次。

刚才说「访问淘汰」的逻辑只会在Master角色上发生,那「访问淘汰」也是吗?

一般来说,Slave节点不会进行定时淘汰,它只会等待从Master节点同步过来的删除命令,这样就保持了主从之间的一致性。然而,有些时候,用户会把Slave节点设置成可写,那么Slave上写的带有过期时间的Key,因为Master是不知道的,就一直不会淘汰掉。所以在版本4.0以后,Redis增加了单独的逻辑,在定时淘汰中删除这些在slave节点上写入的过期Key。

对于Master节点,根据宏ACTIVE_EXPIRE_CYCLE_SLOW,能选择两种淘汰模式,分别是“FAST淘汰”和“SLOW淘汰”,前者每次淘汰只能花1毫秒,不能花更多了,后者是Qcloud默认的选项,这样能在每次调度中淘汰更多的Key,但会花更多的CPU时间在淘汰上,降低了处理的访问吞吐量。下面我们针对“SLOW淘汰”展开描述。

SLOW淘汰模式,以hz=10为例,每次调度的总时间是100ms,这里调度不会25%的cpu时间,即25ms。

每淘汰多少个key,就检测一次是否超25ms呢?

如果每淘汰1个Key就检测一次,无疑代价太大。从源码上看,定时淘汰会尝试遍历每个db,遍历完了或者时间到了就退出循环。第一层循环是遍历各个db,第二层循环是遍历db里面的一批批key,一批key是20个,如果第三层循环结束后有大于5个key是成功淘汰的(说明这个db很多淘汰key),那么二层就继续循环,如果小于等于5个key,说明这个db没有很多key需要淘汰,则退出二层循环,第三层循环是一批key里面逐个key进行淘汰。即最多320个key进行判断后,就会看看是否已经超过cpu占用时间。

在4.0或以上的版本,会根据参数lazyfree-lazy-expire(默认no)来做DEL还是UNLINK。在Qcloud的4.0以上版本,这里会特意配置成yes,以便尽量采用UNLINK操作。2.8版本不支持lazyfree-lazy-expire,就只能选择DEL命令。

这里的定时淘汰,也会以命令的形式,传播到Slave节点与记录到AOF文件中。

1

1.驱逐策略的选择,往往与业务特点、使用场景紧密相关。不当的选择,可能会让用户丢失不想丢失的数据,或者导致较差的驱逐效率;

2.已过期的Key往往不会立刻被删除,用户在导出快照与建立主从时,会疑惑主从之间的Key数量不一致,我们都需要了解这一点;

3.驱逐与淘汰都有可能影响服务,在新版本下,最好都开启unlink代替del。

5分钟学会这种更高效的Redis数据删除方式

直播预告

5分钟学会这种更高效的Redis数据删除方式

5分钟学会这种更高效的Redis数据删除方式

特惠体验云数据库 

5分钟学会这种更高效的Redis数据删除方式

↓↓更多惊喜优惠请点这儿~


以上所述就是小编给大家介绍的《5分钟学会这种更高效的Redis数据删除方式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Go Web 编程

Go Web 编程

[新加坡]Sau Sheong Chang(郑兆雄) / 黄健宏 / 人民邮电出版社 / 2017-11-22 / 79

《Go Web 编程》原名《Go Web Programming》,原书由新加坡开发者郑兆雄(Sau Sheong Chang)创作、 Manning 出版社出版,人名邮电出版社引进了该书的中文版权,并将其交由黄健宏进行翻译。 《Go Web 编程》一书围绕一个网络论坛 作为例子,教授读者如何使用请求处理器、多路复用器、模板引擎、存储系统等核心组件去构建一个 Go Web 应用,然后在该应用......一起来看看 《Go Web 编程》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具