前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于redis的keys、scan删除ttl为-1的key

基于redis的keys、scan删除ttl为-1的key

作者头像
码农编程进阶笔记
发布2022-08-18 08:40:32
8210
发布2022-08-18 08:40:32
举报

前言:由于redis服务器最大使用内存为450MB,redis存储的部分key没有设置过期时间,内存淘汰策略为:noeviction 以上原因导致redis服务无法加载到新的key,迫使部分业务受阻。

一、keys命令介绍

redis KEYS 命令基本语法如下:

代码语言:javascript
复制
redis 127.0.0.1:6379> KEYS PATTERN

返回值

符合给定模式的 key 列表 (Array)。

代码语言:javascript
复制
#获取 redis 中所有的 key 可用使用 *。
redis 127.0.0.1:6379> KEYS *
) "runoob3"
) "runoob1"
) "runoob2"

由于 Redis 是单线程在处理用户的命令,而 Keys 命令会一次性遍历所有 Key,于是在 命令执行过程中,无法执行其他命令。这就导致如果 Redis 中的 key 比较多,那么 Keys 命令执行时间就会比较长,从而阻塞 Redis。

代码语言:javascript
复制
#查找以 runoob 为开头的 key:
redis 127.0.0.1:6379> KEYS runoob*
) "runoob3"
) "runoob1"
) "runoob2"

Keys 的缺点:

  • 没有limit,我们只能一次性获取所有符合条件的key,如果结果有上百万条,那么等待你的就是“无穷无尽”的字符串输出。
  • keys命令是遍历算法,时间复杂度是O(N)。如我们刚才所说,这个命令非常容易导致Redis服务卡顿。因此,我们要尽量避免在生产环境使用该命令。

二、scan命令介绍

Redis Scan 命令用于迭代数据库中的数据库键。

SCAN 命令是一个基于游标的迭代器,每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。

SCAN 返回一个包含两个元素的数组, 第一个元素是用于进行下一次迭代的新游标, 而第二个元素则是一个数组, 这个数组中包含了所有被迭代的元素。如果新游标返回 0 表示迭代已结束。

redis Scan 命令基本语法如下:

代码语言:javascript
复制
SCAN cursor [MATCH pattern] [COUNT count]
参数:
cursor - 游标。
pattern - 匹配的模式。
count - 指定从数据集里返回多少元素,默认值为 10 。

返回值:数组列表。

Scan命令就是对这个一维数组进行遍历。每次返回的游标值也都是这个数组的索引。Count 参数表示遍历多少个数组的元素,将这些元素下挂接的符合条件的结果都返回。因为每个元素下挂接的链表大小不同,所以每次返回的结果数量也就不同。

代码语言:javascript
复制
# 使用 0 作为游标,开始新的迭代
redis 127.0.0.1:6379> scan 0   
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"

#使用的是第一次迭代时返回的游标 17 开始新的迭代
redis 127.0.0.1:6379> scan 17  
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"

Scan 的特点:

  1. 复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程;
  2. 提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是一个 hint,返回的结果可多可少;
  3. 同 keys 一样,它也提供模式匹配功能;
  4. 服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数;
  5. 返回的结果可能会有重复,需要客户端去重复,这点非常重要;
  6. 遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;
  7. 单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零

count参数详解:

  • 当count参数指定为100时,然而redis中key有几百万时,这个时候返回时间会很长,
  • count参数调大后,减少了交互次数,返回的时间就会减少。
  • Count 参数越大,Redis 阻塞时间也会越长,需要取舍。
  • 极限一点,Count 参数和总 Key 数一致时,Scan 命令就和 Keys 效果一样了。

Count 大小和 Scan 总耗时的关系如下图:

结论:

  1. 可以发现 Count 越大,总耗时就越短,不过越后面提升就越不明显了。
  2. 所以推荐的 Count 大小为 1W 左右。
  3. 如果不考虑 Redis 的阻塞,其实 Keys 比 Scan 会快很多,毕竟一次性处理,省去了多余的交互。

三、keys命令删除

代码语言:javascript
复制
#!/usr/bin/python3
import redis

r = redis.Redis(host='172.18.158.92', port=, db=,decode_responses=True)
var = 
var1 = 
list_keys = r.keys("system_WXMINI/WX_MINI_NO_Userinfo/unionid*")

for key in list_keys:
    num = r.ttl(key)
    if num == -1:
        r.delete(key)
        var = var + 
    else:
        var1 = var1 + 

print("end")
print("删除key的数量",var)
print("未删除的数量",var1)

四、scan命令删除

代码语言:javascript
复制
[root@iZwz9conqz5shxfx2gmnfkZ scripts]# cat clean_key_v5.py 
#!/usr/bin/python3
import redis

def RedisScan(vague_key,host="127.0.0.1",port=,password=None,db=):
    redis_cache = redis.Redis(host=host, port=port, db=db, password=password, decode_responses=True)
    begin_pos,counts,var,delete_key = ,,,

    while True:
        begin_pos,list_keys = redis_cache.scan(begin_pos,vague_key,)
        counts += len(list_keys)
        for key in list_keys:
            num = redis_cache.ttl(key)
            if num == -1:
                redis_cache.delete(key)
                delete_key = delete_key + 
            else:
                var = var + 
        if begin_pos == :
            break

    print("no delete key is ", var)
    print("delete key is ", delete_key)
    print("total key is ", counts)

#调用
RedisScan("system_url_id*","172.18.158.92",,"*****")

五、redis 相关调整

代码语言:javascript
复制
CONFIG SET maxmemory-policy volatile-lru

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

本文分享自 码农编程进阶笔记 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档