Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Redis删除特定前缀key的优雅实现

Redis删除特定前缀key的优雅实现

作者头像
小尘哥
发布于 2019-06-24 12:54:19
发布于 2019-06-24 12:54:19
2.9K00
代码可运行
举报
文章被收录于专栏:小尘哥的专栏小尘哥的专栏
运行总次数:0
代码可运行

还在用keys命令模糊匹配删除数据吗?这就是一颗随时爆炸的炸弹!

Redis中没有批量删除特定前缀key的指令,但我们往往需要根据前缀来删除,那么究竟该怎么做呢?可能你一通搜索后会得到下边的答案

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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命令的基本用法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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命令的迭代过程示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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命令遍历大量数据而导致服务器阻塞的情况,使用下边的指令可以达到优雅删除的目的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
redis-cli --scan --pattern "ops-coffee-*" | xargs -L 2000 redis-cli del

其中xargs -L指令表示xargs一次读取的行数,也就是每次删除的key数量,一次读取太多xargs会报错

其他几种数据结构的优雅删除

类似的SCAN命令,对于Redis不同的数据类型还有另外几个SSCANHSCANZSCAN,使用方法类似:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
> 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使用下边的代码可以实现优雅的批量删除:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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使用下边的代码实现优雅的删除:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import redis

def del_big_hash_key(key_name):
    r = redis.StrictRedis(host='localhost', port=6379)

    # hscan_iter获取出来的结果是个元祖,下边hdel删除用key[0]取到key
    for key in r.hscan_iter(name=key_name, count=300):
        r.hdel(key_name, key[0])

del_big_hash_key('ops-coffee')

对于大的有序集合的删除就比较简单了,直接根据zremrangebyrank排行范围删除

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import redis

def del_big_sort_key(key_name):
    r = redis.StrictRedis(host='localhost', port=6379)

    while r.zcard(key_name) > 0:
        # 判断集合中是否有元素,如有有则删除排行0-99的元素
        r.zremrangebyrank(key_name, 0, 99)

del_big_sort_key('ops-coffee')

big list大列表的删除可以参考上边这个方法,通过llen判断数量,然后ltrim移除范围内的元素,这里不赘述

至此对于Redis的五中数据结构大key的优雅删除就全部实现了,生产环境择优使用~


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陌与尘埃 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Redis如何删除数量过万以上Key而不影响业务
有时候因为 Redis Key 没有设置过期时间或者因为业务需求或者Redis内存不足或者修改Redis Key值等需求,并且这些Key是有规律的,可以通过正则表达式来匹配。
YP小站
2021/04/07
4.7K0
【实战】如何使用 Python 从 Redis 中删除 4000万 KEY
本文主要涉及 Redis 的以下两个操作和其 Python 实现,目录: SCAN 命令 DEL 命令 使用 Python SCAN 使用 Python DEL 成果展示 ---- SCAN 命令 SCAN 命令及相关的 SSCAN、HSCAN 和 ZSCAN 命令都用于增量迭代(incrementally iterate)一个集合的元素(a collection of elements): SCAN 用于迭代当前数据库中的数据库键 SSCAN 用于迭代集合键中的元素 HSCAN 用于迭代哈希键中的键值对
临书
2018/03/07
9.2K0
【实战】如何使用 Python 从 Redis 中删除 4000万 KEY
面试官:Redis 大 key 要如何处理?
使用 SCAN 命令对数据库扫描,然后用 TYPE 命令获取返回的每一个 key 的类型。
小林coding
2022/10/27
7010
Redis中Scan命令的使用
Redis中有一个经典的问题,在巨大的数据量的情况下,做类似于查找符合某种规则的Key的信息,这里就有两种方式, 一是keys命令,简单粗暴,由于Redis单线程这一特性,keys命令是以阻塞的方式执行的,keys是以遍历的方式实现的复杂度是 O(n),Redis库中的key越多,查找实现代价越大,产生的阻塞时间越长。
星哥玩云
2022/08/18
1.7K0
Redis中Scan命令的使用
Redis 删除1.2亿指定前缀的key
因为更换IDC的原因,我们需要迁移缓存到新的机房,开发同学提出老的缓存有1.2亿无效(未设置过期时间)的key和正常在用的业务key,在迁移之前可以先指定前缀将key删除。那么问题来了,如何快速删除1.2亿的key呢?
用户1278550
2018/08/09
4K0
Redis之MoreKey问题及Scan命令解读
对于海量数据执行key *会造成严重服务卡顿、影响业务。在实际环境中最好不要使用。生产制造过程中keys * / flushdb/flushall等危险命令以防止误删误用。
一个风轻云淡
2023/09/24
2780
如何优雅的删除一个超过3000多万成员且内存占用超过1.8G的bigkey?
Redis被广泛的应用,得益于它支持高性能访问(微秒级)。作为一个DBA,经常需要去维护bigkey。如果现在业务方需要你去删除一个hash类型的key,且这个key有3000多万个成员,内存占用超过1.8G。如何优雅的删除这个bigkey呢?下面让我来简单的介绍一下。
用户10842762
2023/12/22
4491
如何优雅的删除一个超过3000多万成员且内存占用超过1.8G的bigkey?
Redis中Scan命令的基本用法
SCAN 命令以及比较相近的 SSCAN、HSCAN 和 ZSCAN 命令都用于增量迭代数据集元素:
smartsi
2019/12/17
7.5K0
Redis-脚本-获取某个前缀的key
在平时的维护中,经常会遇到要统计某个前缀的key有多少,在请求比较多的redis中,keys * 会直接导致阻塞。 可以采用scan的方式进行增量迭代,查询使用pipeline减少交互,提高效率。
用户5522200
2019/06/02
3.4K0
Redis:04---键的基本命令(上)
第二次执行“scan 10”,因为上一次返回10,所以从“cursor=10”开始扫描,结果如下所示,返回10个键
用户3479834
2021/02/03
5060
Redis:04---键的基本命令(上)
Redis BigKey介绍
在Redis中,一个字符串最大512MB,一个二级数据结构(例如hash、list、set、zset)可以存储大约40亿个(2^32-1)个元素,但实际上中如果下面两种情况,我就会认为它是bigkey。
OwenZhang
2021/12/07
1.2K0
Redis进阶-如何从海量的 key 中找出特定的key列表 & Scan详解
假设你需要从 Redis 实例成千上万的 key 中找出特定前缀的 key 列表来手动处理数据,可能是修改它的值,也可能是删除 key。那该如何从海量的 key 中找出满足特定前缀的 key 列表来?
小小工匠
2021/08/17
5.2K0
Redis SCAN的使用
有时候需要从 Redis 实例成千上万的 key 中找出特定前缀的 key 列表来手动处理数据,可能是修改它的值,也可能是删除 key。这里就有一个问题,如何从海量的 key 中找出满足特定前缀的 key 列表来?
小歪
2019/09/26
3.1K0
Redis命令:scan实现模糊查询
从Redis v2.8开始,SCAN命令已经可用,它允许使用游标从keyspace中检索键。 对比KEYS命令,虽然SCAN无法一次性返回所有匹配结果,但是却规避了阻塞系统这个高风险,从而也让一些操作可以放在主节点上执行。
用户1205080
2018/12/10
6.3K0
获取Redis中所有的键
在日常的开发中我们有时会要遍历Redis中的所有的键,我们在之前的文章中已经介绍过了,我们可以用keys命令来获取所有的键,那么在Redis中除了keys命令之外,我们还可以使用scan命令获取。下面我们将详细了解一下这两种命令的相关内容。
吉林乌拉
2019/10/15
8.3K0
获取Redis中所有的键
Redis 概览
KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。
三产
2021/01/12
5840
Redis如何批量删除指定前缀的key
批量删除指定前缀的Key有两中方法,一种是借助 redis-cli,另一种是通过 SCAN 命令来遍历所有匹配前缀的 key,并使用 DEL 命令逐个删除它们。
孟斯特
2023/10/16
7.2K0
Redis如何批量删除指定前缀的key
redis的设计规范
部分内容参考:阿里redis开发规范 同时,结合shigen在实习中的实践经验总结。
shigen
2023/09/16
3110
Redis Hash(Hash) 复习
哈希相当于一个二维数组,内部是无序字典。 哈希也是是一个 string 类型的 field(字段) 和 value(值) 的映射表,所以哈希特别适合用于存储对象。
陈大剩博客
2023/03/06
1.7K0
Redis Hash(Hash) 复习
019.Redis键管理命令
dbsize命令在计算键总数时不会遍历所有键,而是直接获取Redis内置的键总数变量,所以dbsize命令的时间复杂度是O(1)。
CoderJed
2020/12/07
3850
019.Redis键管理命令
相关推荐
Redis如何删除数量过万以上Key而不影响业务
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验