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

分钟,学会,这种,高效,redis,数据,删除,方式 · 浏览次数 : 0

小编点评

**Redis 数据删除机制** **同步删除** * 使用 `DEL` 命令删除数据。 * 如果数据类型复杂,可能导致阻塞,影响性能。 * 仅适用于 4.0 版本以上。 **异步删除** * 使用 `UNLINK` 命令删除数据。 * 性能比同步删除更高,但更复杂。 * 仅适用于 4.0 版本以上。 **Key 驱逐** * 随着数据存储的增加,数据库会进行 Key 驱逐,删除过期的 Key。 * 驱逐策略取决于 `maxmemory` 参数,有以下几种策略: * `volatile-random` 从最近过期的 Key 中选择数据。 * `volatile-lru` 从最近最少使用的数据中选择数据。 * `volatile-ttl` 从最近过期的 Key 中选择数据。 * `allkeys-random` 从所有数据中选择数据。 * `allkeys-lru` 从所有数据中选择最近最少使用的数据。 * `noeviction` 禁止驱逐数据,永远不删除。 * `lazyfree-lazy_eviction` 在 expire 时选择使用 `del` 或 `unlink`。 * `lazyfree-lazy_expire` 在 expire 时选择使用 `del` 或 `unlink`,默认值为 `no`。 **定时淘汰** * 每天执行一次定时调度,删除过期的 Key。 * 每个 db 中,最多执行 320 个 key。 * 每个 db 最多进行 5 次淘汰。 * 如果发现超过 5 个 key 淘汰成功,则退出循环。 **其他** * 当设置 `lazyfree-lazy_expire` 时,仅使用 `unlink`。 * 4.0 版本以上版本,`lazyfree-lazy_expire` 默认值为 `no`,使用 `del` 命令进行删除。

正文

https://ost.51cto.com/posts/12513

 

简述

 

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

 

同步和异步删除

 

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。

 

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节点。

 

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

 

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

 

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

 

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

5分钟学会这种更高效的Redis数据删除方式-开源基础软件社区

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

 

与[转帖]5分钟学会这种更高效的Redis数据删除方式相似的内容:

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

https://ost.51cto.com/posts/12513 简述 我们知道,Del命令能删除数据,除此之外,数据在Redis中,还会以哪种方式被删除呢?在Redis内存满一定会返回OOM错误?Key到达过期时间就立即删除?删除大Key会影响性能吗?下面,咱们一起探讨。 同步和异步删除 1.D

[转帖]Centos下使用containerd管理容器:5分钟从docker转型到containerd

https://www.cnblogs.com/renshengdezheli/p/16684175.html 目录 一.系统环境 二.前言 三.containerd 四.部署containerd 4.1 安装containerd 4.2 containerd配置文件 4.3 配置container

[转帖]20191022-从Jenkins NativeOOM到Java8内存

我把老掉牙的Jenkins升级了,它跑了几天好好的;后来我有一个python脚本使用JenkinsAPI 0.3.9每隔2.5分钟发送约300余get请求,结果过了3天,它就挂了;当我开两个脚本时,40.5小时就挂了。(可以通过搜索Jenkins日志/var/log/jenkins/* 中字符Jen

【转帖】纳尼,mysqldump导出的数据居然少了40万?

0、导读 用mysqldump备份数据时,加上 -w 条件选项过滤部分数据,发现导出结果比实际少了40万,什么情况? 本文约1500字,阅读时间约5分钟。 1、问题 我的朋友小文前几天遇到一个怪事,他用mysqldump备份数据时,加上了 -w 选项过滤部分数据,发现导出的数据比实际上少了40万。

[转帖]《Linux性能优化实战》笔记(一)—— 平均负载

最近在看极客时间的《Linux性能优化实战》课程,记录下学习内容。 一、 平均负载(Load Average) 1. 概念 我们都知道uptime命令的最后三列分别是过去 1 分钟、5 分钟、15 分钟系统的平均负载,到底平均负载是什么? 简单来说,平均负载是指单位时间内,系统处于可运行状态和不可中

[转帖]超能课堂(323) 为什么WiFi实际速率只有标称速率的一半?

超能课堂(323) 为什么WiFi实际速率只有标称速率的一半? 开始的地方 协议速率与实际速率有何不同? 什么是“全双工”与“半双工”? 无线网络与有线网络的抗干扰能力不在一个级别 无线网络与有线网络其实是相辅相成的 本文约 2730 字、5 张图表,需 5 分钟阅读 (切换至标准版) 在我们的实际

[转帖]TiDB 适配应用实践:MyBatis 3.5.X 在 JDK8 中性能问题的排查与优化

https://zhuanlan.zhihu.com/p/371638037 作者介绍:PingCAP Tech Center,于旸。 最近有金融客户使用 TiDB 适配批处理场景,数据量在数亿级。对于相同数据量的处理耗时,TiDB 要 35 分钟,而某商业数据库只要 15 分钟,足足相差 20 分

[转帖]5、docker 访问仓库

很早之前看的文章,进行了简单的排版整理,找不到源地址了,如有侵权,请联系删除。 仓库(Repository)是集中存放镜像的地方。 一个容易混淆的概念是注册服务器(Registry)。实际上注册服务器是管理仓库的具体服务器,每个服务器上可以有多个仓库,而每个仓库下面有多个镜像。从这方面来说,仓库可以

[转帖]5个相见恨晚的Linux命令

https://www.sohu.com/a/295860653_487482 编者按:说到Linux命令相信大家都不陌生,就连前端现在也要经常在 terminal 敲一些 node,gulp等命令,本文详细介绍了五个相见恨晚,能极大提高工作效率的命令。 tldr(命令手册) 作为一个开发人员,经常

[转帖]5个相见恨晚的Linux命令

https://www.sohu.com/a/295860653_487482 编者按:说到Linux命令相信大家都不陌生,就连前端现在也要经常在 terminal 敲一些 node,gulp等命令,本文详细介绍了五个相见恨晚,能极大提高工作效率的命令。 tldr(命令手册) 作为一个开发人员,经常