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

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

本文主要给大家展示“Redis如何删除1.2亿指定前缀的密钥”,简单易懂,条理清晰,希望能帮你解决疑惑。让边肖带领大家学习学习《Redis如何删除1.2亿指定前缀的密钥》一文。

背景

因为IDC的更换,我们需要将缓存迁移到新的机房。开发同学建议旧缓存有1.2亿个无效密钥(没有设置过期时间)和正常使用的业务密钥。在迁移之前,您可以指定前缀来删除密钥。那么问题来了,如何快速删除1.2亿个密钥?

如何获取指定的密钥

众所周知,由于Redis的单线程服务模式,订购keys *会阻塞正常的业务请求,所以肯定不行。

这里我们使用Redis提供的SCAN函数。scan命令是一个基于游标的迭代器:每次调用SCAN命令时,它都会向用户返回一个新的游标,用户需要在下一次迭代中使用这个新的游标作为SCAN命令的游标参数,以便继续上一次迭代过程。

当SCAN命令的游标参数设置为0时,服务器将开始新的迭代,当服务器向用户返回一个值为0的游标时,意味着迭代已经结束。扫描具有以下语法

扫描光标[匹配模式][计数]

Cousor是一个游标,MATCH支持常规匹配。我们可以只利用这个函数,比如匹配前缀为‘DBA _’的键,COUNT就是每次获得多少个键。

redis127.0.0.1:6379scan0

1)'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:637917

1)'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,这意味着迭代已经结束,整个集合已经被完全遍历。

从上面的例子可以看出,s can命令的回复是一个包含两个元素的数组,第一个数组元素是下一次迭代的新光标,第二个数组元素是一个数组,包含所有迭代的元素。

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

Python redis模块提供sca

n_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) 2
127.0.0.1:6379[2]>

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

(mytest)?  test git:(master) ? python delete_key.py
initial keys successfully,use time: 90.2497739792
normal ways end at: 68.685477972
normal 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,发送网络请求。

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

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

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

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

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

代码

  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”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/129599.html

(0)

相关推荐

  • SpringBoot HATEOAS的原理是什么

    技术SpringBoot HATEOAS的原理是什么本篇文章给大家分享的是有关SpringBoot HATEOAS的原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小

    攻略 2021年11月23日
  • CF 1500 C

    技术CF 1500 C CF 1500 CCF 1500 C
    题意:
    ? 给你两个 \(n \times m\) 的矩阵 A,B(1 \(\leq\) n,m \(\leq\) 1500),矩阵的元素均

    礼包 2021年11月30日
  • 删除字符串中所有的空格

    技术删除字符串中所有的空格 删除字符串中所有的空格1 题目函数:fun()
    功能:删除字符串中所有的空格
    举例:
    主函数中输入“fds afadsf adf d dsf 67d”
    则输出:“fds

    礼包 2021年11月10日
  • idea 远程debug

    技术idea 远程debug idea 远程debug1.pom.xml里配置jvmArguments参数 -Xdebug -Xrunjdwp:transport=dt_socket,address=5

    礼包 2021年11月26日
  • Python基础知识-1.7标识符和关键字

    技术Python基础知识-1.7标识符和关键字 Python基础知识-1.7标识符和关键字一、标识符上图看完了,那什么是标识符
    答:在程序中定义的一些符号和名称
    二、作用
    前面学习变量了,下面的代码,此

    礼包 2021年12月5日
  • 怎么用树莓派来做下载机

    技术怎么用树莓派来做下载机这篇文章主要介绍了怎么用树莓派来做下载机,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。 树莓派做下载机的优点就是功耗小,2

    攻略 2021年11月20日