千家信息网

Redis如何删除1.2亿指定前缀的key

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要为大家展示了"Redis如何删除1.2亿指定前缀的key",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Redis如何删除1.2亿指定前缀的ke
千家信息网最后更新 2026年11月02日Redis如何删除1.2亿指定前缀的key

这篇文章主要为大家展示了"Redis如何删除1.2亿指定前缀的key",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Redis如何删除1.2亿指定前缀的key"这篇文章吧。

背景

因为更换IDC的原因,我们需要迁移缓存到新的机房,开发同学提出老的缓存有1.2亿无效(未设置过期时间)的key和正常在用的业务key,在迁移之前可以先指定前缀将key删除。那么问题来了,如何快速删除1.2亿的key呢?

如何获取指定的 key

大家都知道由于Redis的单线程服务模式,命令 keys * 会阻塞正常的业务请求,所以肯定不行。

在这里我们利用Redis 提供的 SCAN 功能。SCAN 命令是一个基于游标的迭代器(cursor based iterator): SCAN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。

当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。 SCAN的语法如下

SCAN cursor [MATCH pattern] [COUNT count]

其中 cousor 是游标,MATCH 则支持正则匹配,我们正好可以利用此功能,比如匹配 前缀为"dba_"的key, COUNT 是每次获取多少个key。

redis 127.0.0.1:6379> scan 01) "17"2)  1) "key:12"    2) "key:8"    3) "key:4"    4) "key:14"    5) "key:16"    6) "key:17"    7) "key:15"    8) "key:10"    9) "key:3"    10) "key:7"    11) "key:1"redis 127.0.0.1:6379> scan 171) "0"2) 1) "key:5"   2) "key:18"   3) "key:0"   4) "key:2"   5) "key:19"   6) "key:13"   7) "key:6"   8) "key:9"   9) "key:11"

在上面这个例子中, 第一次迭代使用 0 作为游标, 表示开始一次新的迭代。第二次迭代使用的是第一次迭代时返回的游标, 也即是命令回复第一个元素的值 -- 17 。 在第二次调用 SCAN 命令时, 命令返回了游标 0 , 这表示迭代已经结束, 整个数据集(collection)已经被完整遍历过了。

从上面的示例可以看到, SCAN 命令的回复是一个包含两个元素的数组, 第一个数组元素是用于进行下一次迭代的新游标, 而第二个数组元素则是一个数组, 这个数组中包含了所有被迭代的元素。

注意:以 0 作为游标开始一次新的迭代, 一直调用 SCAN 命令, 直到命令返回游标 0 , 我们称这个过程为一次完整遍历(full iteration)。 我们会在后面的代码实现中利用此特点。

Python的redis 模块提供 scan_iter 迭代器来遍历key,其返回的结果迭代器对象。

In [53]: ret=r.scan_iter('dba_*',20)In [54]: print ret

至此,我们解决了如何获取数据的问题,下面思考第二个问题。

如何执行删除

这个相对比较简单,Redis 提供DEL 命令

127.0.0.1:6379[2]> get "dba_7""r06cVX9"127.0.0.1:6379[2]> get "dba_1""ETX57PA"127.0.0.1:6379[2]> del "dba_7" "dba_1"(integer) 2127.0.0.1:6379[2]>

在redis-py 中,提供了delete(key),delete(*key)的函数, 其中参数 *key 是多个值的列表。 到这里,我们大致可以想到获取key,然后批量删除

(mytest)?  test git:(master) ? python delete_key.pyinitial keys successfully,use time: 90.2497739792normal ways end at: 68.685477972normal ways delete numbers: 1000000

常规方式的删除10W个key耗时68.7秒,如果是1.2亿个key 要多少时间呢?68*1000/3600=18.8小时。能不能更快呢?

如何提高执行速度

Redis本身是基于Request/Response协议的,客户端发送一个命令,等待Redis应答,Redis在接收到命令,处理后应答。其中发送命令加上返回结果的时间称为(Round Time Trip)RRT-往返时间。如果客户端发送大量的命令给Redis,那就是等待上一条命令应答后再执行再执行下一条命令,这中间不仅仅多了RTT,而且还频繁的调用系统IO,发送网络请求。

Pipeline(流水线)功能极大的改善了上面的缺点。Pipeline能将一组Redis命令进行组装,然后一次性传输给Redis,再将Redis执行这组命令的结果按照顺序返回给客户端。

需要注意的是Pipeline 虽然好用,但是Pipline组装的命令个数不能没有限制,否则一次组装数据量过大,一方面增加客户端的等待时间,另一方面会造成网络阻塞,需要批量组装。使用Pepline 和常规方式的性能对比如下:

代码

  1. # encoding: utf-8

  2. """

  3. author: yangyi@youzan.com

  4. time: 2018/3/9 下午8:35

  5. func:

  6. """

  7. import redis

  8. import random

  9. import string

  10. import time

  11. pool = redis.ConnectionPool(host='127.0.0.1', port=6379, db=2)

  12. r = redis.Redis(connection_pool=pool)



  13. def random_str():

  14. return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(7))



  15. def init_keys():

  16. start_time = time.time()

  17. for i in xrange(0, 20):

  18. key_name = 'dba_'+str(i)

  19. value_name = random_str()

  20. r.set(key_name, value_name)

  21. print 'initial keys successfully,use time:', time.time() - start_time



  22. def del_keys_without_pipe():

  23. start_time = time.time()

  24. result_length = 0

  25. for key in r.scan_iter(match='dba_*', count=2000):

  26. r.delete(key)

  27. result_length += 1

  28. print "normal ways end at:", time.time() - start_time

  29. print "normal ways delete numbers:", result_length



  30. def del_keys_with_pipe():

  31. start_time = time.time()

  32. result_length = 0

  33. pipe = r.pipeline()

  34. for key in r.scan_iter(match='dba_*', count=5000):

  35. pipe.delete(key)

  36. result_length += 1

  37. if result_length % 5000 == 0:

  38. pipe.execute()

  39. pip_time = time.time()

  40. print "use pipeline scan time ", time.time() - start_time

  41. pipe.execute()


  42. print "use pipeline end at:", time.time() - pip_time

  43. print "use pipeline ways delete numbers:", result_length



  44. def main():

  45. init_keys()

  46. del_keys_without_pipe()

  47. init_keys()

  48. del_keys_with_pipe()



  49. if __name__ == '__main__':

  50. main()

以上是"Redis如何删除1.2亿指定前缀的key"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

命令 迭代 游标 前缀 元素 时间 客户 数组 内容 功能 参数 客户端 数据 用户 篇文章 结果 问题 面的 服务 业务 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司 亿人帮互联网科技有限公司 互联网科技活动banner 互联网金融 科技 万易互联网科技 顺玮阁互联网科技 互联网实体化科技化 茂名市互联网科技产业园 广西互联网科技孵化中心 科技类公司包括互联网吗 互联网新科技动漫ppt素材 河南住房之家互联网科技 互联网公司黑科技创始人 群盈汇互联网科技有限公司 合肥互联网科技公司公章图片 伍佰万互联网科技怎么赚钱 广州百诚互联网科技有限公司官网 领航科技大厦互联网公司 广州有谷有贝互联网科技有限公司 安徽零酒互联网科技有限公司 科技互联网政务服务 深圳科技互联网 广州宏创互联网科技 齐家互联网科技有限公司 互联网和黑科技的看法 苏州铭阳互联网科技有限公司 互联网媒体平台算高科技产业 科技类公司包括互联网吗 杭州披云加互联网科技有限公司 互联网科技数字货币
0