Redis删除特定前缀key的优雅实现
还在用keys命令模糊匹配删除数据吗?这就是一颗随时爆炸的炸弹!
Redis中没有批量删除特定前缀key的指令,但我们往往需要根据前缀来删除,那么究竟该怎么做呢?可能你一通搜索后会得到下边的答案
redis-cli --raw keys "ops-coffee-*" | xargs redis-cli del
直接在linux下通过redis的keys命令匹配到所有的key,然后调用系统命令xargs来删除,看似非常完美,实则风险巨大
因为Redis的单线程服务模式,命令keys会阻塞正常的业务请求,如果你一次keys匹配的数量过多或者在del的时候遇到大key,都会直接导致业务的不可用,甚至造成redis宕机的风险
所以我们在生产环境中应当避免使用上边的方法,那有什么优雅的方法来解决呢?SCAN!
SCAN介绍及使用
Redis从2.8版本开始支持scan命令,SCAN命令的基本用法如下:
SCAN cursor [MATCH pattern] [COUNT count]
cursor: 游标,SCAN命令是一个基于游标的迭代器,SCAN命令每次被调用之后,都会向用户返回一个新的游标,用户在下次迭代时需要使用这个新游标作为SCAN命令的游标参数,以此来延续之前的迭代过程,直到服务器向用户返回值为0的游标时,一次完整的遍历过程就结束了
MATCH: 匹配规则,例如遍历以ops-coffee-开头的所有key可以写成ops-coffee-*,中间包含-coffee-的可以写成*-coffee-*
COUNT: COUNT选项的作用就是让用户告知迭代命令,在每次迭代中应该从数据集里返回多少元素,COUNT只是对增量式迭代命令的一种提示,并不代表真正返回的数量,例如你COUNT设置为2有可能会返回3个元素,但返回的元素数据会与COUNT设置的正相关,COUNT的默认值是10
以下是一个SCAN命令的迭代过程示例:
127.0.0.1:6379> scan 0 MATCH ops-coffee-*
1) "38"
2) 1) "ops-coffee-25"
2) "ops-coffee-19"
3) "ops-coffee-29"
4) "ops-coffee-10"
5) "ops-coffee-23"
6) "ops-coffee-5"
7) "ops-coffee-14"
8) "ops-coffee-16"
9) "ops-coffee-11"
10) "ops-coffee-15"
11) "ops-coffee-7"
12) "ops-coffee-1"
127.0.0.1:6379> scan 38 MATCH ops-coffee-* COUNT 1000
1) "0"
2) 1) "ops-coffee-13"
2) "ops-coffee-9"
3) "ops-coffee-21"
4) "ops-coffee-6"
5) "ops-coffee-30"
6) "ops-coffee-20"
7) "ops-coffee-2"
8) "ops-coffee-12"
9) "ops-coffee-28"
10) "ops-coffee-3"
11) "ops-coffee-26"
12) "ops-coffee-4"
13) "ops-coffee-31"
14) "ops-coffee-8"
15) "ops-coffee-22"
16) "ops-coffee-27"
17) "ops-coffee-18"
18) "ops-coffee-24"
19) "ops-coffee-17"
SCAN命令返回的是一个包含两个元素的数组,第一个数组元素是用于进行下一次迭代的新游标,而第二个数组元素则是一个数组,这个数组中包含了所有被迭代的元素
上面这个例子的意思是扫描所有前缀为ops-coffee-的key
第一次迭代使用0作为游标,表示开始一次新的迭代,同时使用了MATCH匹配前缀为ops-coffee-的key,返回了游标值38以及遍历到的数据
第二次迭代使用的是第一次迭代时返回的游标,也即是命令回复第一个元素的值38,同时通过将COUNT选项的参数设置为1000,强制命令为本次迭代扫描更多元素
在第二次调用SCAN命令时,命令返回了游标0,这表示迭代已经结束,整个数据集已经被完整遍历过了
KEYS命令的时间复杂度为O(n),而SCAN命令会将遍历操作分解成m次时间复杂度为O(1)的操作来执行,从而解决使用keys命令遍历大量数据而导致服务器阻塞的情况,使用下边的指令可以达到优雅删除的目的:
redis-cli --scan --pattern "ops-coffee-*" | xargs -L 2000 redis-cli del
其中xargs -L指令表示xargs一次读取的行数,也就是每次删除的key数量,一次读取太多xargs会报错
其他几种数据结构的优雅删除
类似的SCAN命令,对于Redis不同的数据类型还有另外几个SSCAN、HSCAN和ZSCAN,使用方法类似:
> sscan ops-coffee 0 MATCH v1*
1) "7"
2) 1) "v15"
2) "v13"
3) "v12"
4) "v10"
5) "v14"
6) "v1"
与SCAN命令不同的是这几个命令需要多加一个key的参数,例如上边的ops-coffee
对于一个大的set key,借助sscan使用下边的代码可以实现优雅的批量删除:
import redis
def del_big_set_key(key_name):
r = redis.StrictRedis(host='localhost', port=6379)
# count表示每次删除的元素数量,这里每次删除300元素
for key in r.sscan_iter(name=key_name, count=300):
r.srem(key_name, key)
del_big_set_key('ops-coffee')
对于一个大的hash key,则可借助hscan使用下边的代码实现优雅的删除:
文章未完,全部内容请关注公众号【运维咖啡吧】或个人网站https://ops-coffee.cn查看,运维咖啡吧专注于原创精品内容分享,感谢您的支持

Redis删除特定前缀key的优雅实现的更多相关文章
- Redis删除相同前缀的key
如何优雅地删除Redis set集合中前缀相同的key? Redis中有删除单条数据的命令DEL,却没有批量删除特定前缀key的指令,但我们经常遇到需要根据前缀来删除的业务场景 ...
- redis删除指定前缀的缓存
redis作为缓存服务器为MySQL数据库提供较高的防御性,对于一些数据的查询可以直接从缓存中可以进行查询. 但是,某些情况下,我们需要清除缓存. 以下场景: 公司经常做活动,每个活动都存在大量的数据 ...
- laravel redis 删除指定前缀的 key
// 前缀 $prefix = 'abc'; // 需要在前面连接上应用的缓存前缀 $keys = app('redis')->keys(config('cache.prefix') . $pr ...
- 批量删除Redis数据库中的Key
批量删除KeyRedis 中有删除单个 Key 的指令 DEL,但好像没有批量删除 Key 的指令,不过我们可以借助 Linux 的 xargs 指令来完成这个动作 redis-cli keys &q ...
- php redis 获取指定前缀的所有key
php redis 获取指定前缀的所有key 以laravel框架为例: $key = $this->redis->keys('db:shipping:shippingId:' . &qu ...
- redis 删除大key集合的方法
redis大key,这里指的是大的集合数据类型,如(set/hash/list/sorted set),一个key包含很多元素.由于redis是单线程,在删除大key(千万级别的set集合)的时候,或 ...
- redis删除单个key和多个key,ssdb会落地导致重启redis无法清除缓存
redis删除单个key和多个key,ssdb会落地导致重启redis无法清除缓存,需要针对单个key进行删除 删除单个:del key 删除多个:redis-cli -a pass(密码) keys ...
- reids中删除某个前缀的所有key
需求:reids中删除某个前缀的所有key 说明:代码中的0:2标识从key前缀中截取前2个字符,这里示例的时候比如“b_”前缀,使用时候根据实际情况截取对应的长度进行判断即可. 生成测试数据 #!/ ...
- worker 启动时向 etcd 注册自己的信息,并设置一个带 TTL 的租约,每隔一段时间更新这个 TTL,如果该 worker 挂掉了,这个 TTL 就会 expire 并删除相应的 key。
1.通过etcd中的选主机制,我们实现了服务的高可用.同时利用systemd对etcd本身进行了保活,只要etcd服务所在的机器没有宕机,进程就具备了容灾性. https://mp.weixin.qq ...
随机推荐
- MSM8909中LK阶段LCM屏适配与显示流程分析(二)
1.前言 在前面的文章MSM8909中LK阶段LCM屏适配与显示流程分析(一),链接如下: https://www.cnblogs.com/Cqlismy/p/12019317.html 介绍了如何使 ...
- h5中的audio音频标签与对应的dom对象
HTML5中提供了一个<audio>标签,同时也提供了一个Audio对象给JavaScript去操作,这个对象属于HTML的DOM对象. H5中的<audio>标签 此标签是H ...
- 对象数组自定义排序--System.Collections.ArrayList.Sort()
使用System.Collections.ArrayList.Sort()对象数组自定义排序 其核心为比较器的实现,比较器为一个类,继承了IComparer接口并实现int IComparer.Com ...
- C# 学习笔记 多态(二)抽象类
多态是类的三大特性之一,抽象类又是多态的实现方法之一.抽象类是什么呢,如果把虚方法比作一个盛有纯净水的杯子,那么此时的“纯净水”就是事先定义好的方法,我们可以根据不同的需求来改变杯子中所事先盛放的是“ ...
- Winform(C#)中Chart控件鼠标点击显示波形上相应点对应坐标轴的x,y值
方法一:鼠标点击波形 鼠标点击波形,显示点击位置的x,y值 private void chart1_MouseClick(object sender, MouseEventArgs e) //cha ...
- Unable to connect to web server 'IIS Express'(无法连接到Web服务器“IIS Express”)的解决方式-Jexus Manager
在运行微软示例工程eShopOnWeb时候, 在经过一段时间再运行启动报Error "Unable to connect to web server 'IIS Express'" ...
- 微信接口调用'updateTimelineShareData','updateAppMessageShareData' 的踩坑记录
6月份新版微信客户端发布后,用户从微信内的网页分享消息给微信好友,以及分享到朋友圈,开发者将无法获知用户是否分享完成.具体调整点为: ()分享接口调用后,不再返回用户是否分享完成事件,即原先的canc ...
- 【spring】自定义注解 custom annotation
自定义注解 custom annotation 使用场景 类属性自动赋值. 验证对象属性完整性. 代替配置文件功能,像spring基于注解的配置. 可以生成文档,像java代码注释中的@see,@pa ...
- Python基础22
数据类型可变不可变,说的是“指向”. 深浅拷贝.
- python中pip添加国内镜像源后显著加速下载
python中pip添加国内镜像源后显著加速下载 更换pip源到国内镜像,很多国外的库下载非常慢,添加国内镜像后安装下载速度提升非常明显(亲测有些可以由几十kb加速到几MB) pip国内的一些镜像阿里 ...