019-批量修改redis TTL和批量删除key

栏目: 数据库 · 发布时间: 6年前

内容简介:这是坚持技术写作计划(含翻译)的第19篇,定个小目标999,每周最少2篇。如果因为历史原因,导致redis里存在无用且没有设置ttl的key,会造成浪费。本文主要讲如何在不阻塞redis的情况下批量修改redis的ttl和使用通配符删除key。其中

这是坚持技术写作计划(含翻译)的第19篇,定个小目标999,每周最少2篇。

如果因为历史原因,导致 redis 里存在无用且没有设置ttl的key,会造成浪费。本文主要讲如何在不阻塞redis的情况下批量修改redis的ttl和使用通配符删除key。

通配符删除key

redis-cli [-a password] [-h localhost] [-p 6379] --scan --pattern pattern* | xargs redis-cli [-a password] [-h localhost] [-p 6379] del

其中 [] 包裹的都是可选项

  • -p 端口
  • -h 是redis主机
  • -a 是密码
  • pattern* 是通配符

    SCAN,SSCAN,HSCAN,ZSCAN四个命令都支持增量式迭代, 它们每次执行都只会返回少量元素, 所以这些命令可以用于生产环境, 而不会出现像 KEYS 命令、 SMEMBERS 命令带来的问题 —— 当 KEYS 命令被用于处理一个大的数据库时, 又或者 SMEMBERS 命令被用于处理一个大的集合键时, 它们可能会阻塞服务器达数秒之久。

参考资料 redis 命令 SCAN

批量打印或者修改TTL

使用方式

$ pip install redis
$ python keys.py --help

usage: keys.py [-h] [-p PORT] [-d DB_LIST] [--host HOST] [--password PASSWORD]
               [--expire EXPIRE] [--random_upper RANDOM_UPPER]
               [--max_ttl MAX_TTL]

optional arguments:
  -h, --help            show this help message and exit
  -p PORT               port of redis
  -d DB_LIST            ex : -d all / -d 1,2,3,4
  --host HOST           ex : --host 127.0.0.1
  --password PASSWORD   ex : --password password
  --expire EXPIRE       unit: sec ,ex 1 days = 86400 sec: --expire 86400
  --random_upper RANDOM_UPPER
                        unit: sec ,ex 1 mins = 60 sec: --random_upper 60
  --max_ttl MAX_TTL     unit: sec ,ex 1 mins = 60 sec: --max_ttl 60
# encoding: utf-8
"""
author: yangyi@youzan.com
time: 2018/4/26 下午4:34
func: 获取数据库中没有设置ttl的 key

author: anjia0532@gmail.com
time: 2019/05/10 上午8:19
desc: 增加cli选项,增加批量修改ttl功能
"""
import redis
import argparse
import time
import sys, os
import random

class ShowProcess:
    
    """
    显示处理进度的类
    调用该类相关函数即可实现处理进度的显示
    """
    i = 0 # 当前的处理进度
    max_steps = 0 # 总共需要处理的次数
    max_arrow = 50 # 进度条的长度

    # 初始化函数,需要知道总共的处理次数
    def __init__(self, max_steps):
        self.max_steps = max_steps
        self.i = 0

    # 显示函数,根据当前的处理进度i显示进度
    # 效果为[>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>]100.00%
    def show_process(self, i = None):
        if i is not None:
            self.i = i
        else:
            self.i += 1
        num_arrow = int(self.i * self.max_arrow / self.max_steps) # 计算显示多少个'>'
        num_line = self.max_arrow - num_arrow # 计算显示多少个'-'
        percent = self.i * 100.0 / self.max_steps # 计算完成进度,格式为xx.xx%
        process_bar = '[' + '>' * num_arrow + ' ' * num_line + ']'\
                      + '%.2f' % percent + '%' + '\r' # 带输出的字符串,'\r'表示不换行回到最左边
        sys.stdout.write(process_bar) # 这两句打印字符到终端
        sys.stdout.flush()

    def close(self, words='done'):
        print(words)
        self.i = 0


def check_ttl(redis_conn, dbindex,max_ttl,random_upper,expire):
    start_time = time.time()
    changed_ttl_num = 0
    keys_num = redis_conn.dbsize()
    print( "there are {num} keys in db {index} ".format(num=keys_num, index=dbindex))
    process_bar = ShowProcess(keys_num)
    for key in redis_conn.scan_iter(count=1000):
        process_bar.show_process()
        ttl = redis_conn.ttl(key)
        if ttl > max_ttl or ttl == -1:
            changed_ttl_num += 1
            redis_conn.expire(key, expire + random.randint(0, random_upper))
        else:
            continue

    process_bar.close()
    print("cost time(s):", time.time() - start_time)
    print("changed ttl keys number:", changed_ttl_num)


def main():
    parser = argparse.ArgumentParser()
    
    parser.add_argument('--port', type=int, dest='port', action='store', default=6379,help='port of redis ')
    parser.add_argument('--db_list', type=str, dest='db_list', action='store', default='0',
                        help='ex : -d all / -d 1,2,3,4 ')
    parser.add_argument('--host', type=str, dest='host', action='store', default='127.0.0.1',
                        help='ex : --host 127.0.0.1 ')
    parser.add_argument('--password', type=str, dest='password', action='store', default='',
                        help='ex : --password password ')
    parser.add_argument('--expire', type=int, dest='expire', action='store', default='0',
                        help='unit: sec ,ex 1 days = 86400 sec: --expire 86400 ')
    parser.add_argument('--random_upper', type=int, dest='random_upper', action='store', default='60',
                        help='unit: sec ,ex 1 mins = 60 sec: --random_upper 60 ')
    parser.add_argument('--max_ttl', type=int, dest='max_ttl', action='store', default='60',
                        help='unit: sec ,ex 1 mins = 60 sec: --max_ttl 60 ')
    
    args = parser.parse_args()
    port = args.port
    expire = args.expire
    random_upper = args.random_upper
    max_ttl = args.max_ttl
    host = args.host
    password = args.password
    
    if args.db_list == 'all':
        db_list = [i for i in range(0, 16)]
    else:
        db_list = [int(i) for i in args.db_list.split(',')]
    for index in db_list:
        try:
            pool = redis.ConnectionPool(host=host, port=port, db=index,password=password)
            r = redis.StrictRedis(connection_pool=pool)
        except redis.exceptions.ConnectionError as e:
            print(e)
        else:
            check_ttl(r, index,max_ttl,random_upper,expire)
if __name__ == '__main__':
    main()

参考资料 【Redis】获取没有设置ttl的key脚本


以上所述就是小编给大家介绍的《019-批量修改redis TTL和批量删除key》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Think Python

Think Python

Allen B. Downey / O'Reilly Media / 2012-8-23 / GBP 29.99

Think Python is an introduction to Python programming for students with no programming experience. It starts with the most basic concepts of programming, and is carefully designed to define all terms ......一起来看看 《Think Python》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具