首页 > 数据库 >redis scan 优雅的批量删除

redis scan 优雅的批量删除

时间:2024-08-13 09:54:49浏览次数:14  
标签:coffee SCAN 迭代 批量 ops scan redis key

参考:
https://ops-coffee.cn/s/x48wmx_k55hmPfZL0tyBYQ.html

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"
    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"
  2. "ops-coffee-15"
  3. "ops-coffee-7"
  4. "ops-coffee-1"
    127.0.0.1:6379> scan 38 MATCH ops-coffee-* COUNT 1000
  5. "0"
    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"
  6. "ops-coffee-3"
  7. "ops-coffee-26"
  8. "ops-coffee-4"
  9. "ops-coffee-31"
  10. "ops-coffee-8"
  11. "ops-coffee-22"
  12. "ops-coffee-27"
  13. "ops-coffee-18"
  14. "ops-coffee-24"
  15. "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"
    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使用下边的代码实现优雅的删除:

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排行范围删除

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的优雅删除就全部实现了,生产环境择优使用~

  ©著作权归作者所有,转载或内容合作请联系作者

作者:夜清溟
链接:https://www.jianshu.com/p/e325015ad5fa
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

标签:coffee,SCAN,迭代,批量,ops,scan,redis,key
From: https://www.cnblogs.com/seasonzone/p/18356258

相关文章

  • 【redis持久化】
    Redis数据持久化Redis作为一个内存数据库,数据是以内存为载体存储的,那么一旦Redis服务器进程退出,服务器中的数据也会消失。为了解决这个问题,Redis提供了持久化机制,也就是把内存中的数据保存到磁盘当中,避免数据意外丢失Redis提供了两种持久化方案:RDB持久化和AOF持久化,一个是......
  • Redis流详解及Java实践
    Redis流详解及Java实践RedisStream概述基本概念使用场景RedisStream命令XADD-添加消息XRANGE-获取消息XREAD-读取消息XGROUP-操作消费者组XACK-确认消息代码示例实战案例示例1:日志收集系统生产者服务消费者服务示例2:消息队列生产者服务消费者服务示......
  • Redis命令之scan的用法和注意细节
    背景Redis提供了scan命令,用于增量迭代获取db里的key。命令格式:SCANcursor[MATCHpattern][COUNTcount]其中SCAN、MATCH、COUNT为命令关键字;cursor为游标,如果为0表示起始,每次执行命令会返回新的cursor,可用于下次命令的增量迭代;pattern为模式,即匹配规则,如Match*表示匹配所......
  • @ComponentScan
    @ComponentScan是一个注解,用于Spring框架,它允许开发者指定Spring应该扫描哪个包或包下的子包来寻找组件(如@Component、@Service、@Repository等注解标注的类)。通过使用@ComponentScan,开发者可以自动化地注册这些组件,使得它们能够被Spring容器管理。语法@ComponentScan注解的......
  • NoSQL之Redis配置与优化
    Redis简介Redis(RemoteDictionaryServer,远程字典型)是一个开源的、使用C语言编写的NoSQL数据库。Redis基于内存运行并支持持久化,采用key-value(键值对)的存储形式,是目前分布式架构中不可或缺的一环Redis优点:具有极高的数据读写速度,数据读取的速度最高可达到110000次/......
  • NoSQL 之Redis集群
    Redis集群的实现方法一般有客户端分片、代理分片和服务器端分片三种解决方案目录一:Redis集群方式主从复制哨兵模式集群模式(Redis-Cluster)二、数据分片方式客户端分片代理分片服务器分片三、故障处理故障转移多slave选举四、Redis群集部署1:安装redis(每个节点......
  • Redis与接口自动化
    1.Redis与接口自动化测试框架的集成使用Python操作Redis需要导入相应的客户端库,例如:pip install redisimportredis2.初始化Redis连接在接口自动化测试框架的初始化过程中,可以添加连接Redis的代码,确保测试过程中能够与Redis建立连接classTestFramework......
  • 【MySQL核心】数据恢复-批量修复 ibd 文件实战-拯救即将跑路的你
    简介本文章主要讲解MySQL异常宕机等意外情况下导致ibd文件损坏,配置mysql强制恢复(innodb_force_recovery)1-6级仍然无法启动的情况。下面是恢复整个实例的所有流程和思路。这里恢复的实例是mysql5.6的整个流程,5.7和5.6类似,8.0可以直接用ibd2sql进行坏表的恢......
  • redis的更新策略以及淘汰策略
    redis更新策略1.先更新缓存再更新数据库:在双写场景下,很容易出现一致性问题,在读写场景下,小概率出现一致性问题,所以Pass。2.先删除缓存再更新数据库:在双写场景下,不会出现一致性问题,在读写场景下,很容易出现一致性问题,所以Pass。3.先更新数据库再更新缓存:在双写场景下,很容易出现一......
  • 一文读懂分布式爬虫利器Scrapy-Redis:源码解析、队列管理与去重策略
    分布式利器Scrapy-Redis原理Scrapy-Redis库已经为我们提供了Scrapy分布式的队列、调度器、去重等功能,其GitHub地址为:https://github.com/rmax/scrapy-redis。本节课我们深入掌握利用Redis实现Scrapy分布式的方法,并深入了解Scrapy-Redis的原理。1.获取源码......