redis 删除大key集合的方法
redis大key,这里指的是大的集合数据类型,如(set/hash/list/sorted set),一个key包含很多元素。由于redis是单线程,在删除大key(千万级别的set集合)的时候,或者清理过期大key数据时,主线程忙于删除这个大key,会导致redis阻塞、崩溃,应用程序异常的情况。
一个例子
线上redis作为实时去重的一个工具,里面有6千万的用户guid,这么一个set集合,如果直接使用del删除,会导致redis严重阻塞。
10.1.254.18:> info memory
# Memory
used_memory:
used_memory_human:.13G
used_memory_rss:
used_memory_peak:
used_memory_peak_human:.82G
used_memory_lua:
mem_fragmentation_ratio:1.47
mem_allocator:jemalloc-3.6.
10.1.254.18:> scard helper_2019--
(integer)
10.1.254.18:> del helper_2019--
(integer)
(.23s)
10.1.254.18:> info memory
# Memory
used_memory:
used_memory_human:.89G
used_memory_rss:
used_memory_peak:
used_memory_peak_human:.82G
used_memory_lua:
mem_fragmentation_ratio:1.26
mem_allocator:jemalloc-3.6.
可以看到,helper_2019-03-12这个key,是一个包含64530980个元素的集合,直接使用del删除命令,花的时间为:81.23s,在超时时间短的苛刻情况下,显然会发送超时,程序异常!好在,我们用的是连接池,没有出现问题。
Java 分批删除
这种情况,应该使用sscan命令,批量删除set集合元素的方法。下面是一个Java代码分批删除redis中set集合的例子:
private static void test2(){
// 连接redis 服务器
Jedis jedis = new Jedis("0.0.0.0",6379);
jedis.auth("123456");
// 分批删除
try {
ScanParams scanParams = new ScanParams();
// 每次删除 500 条
scanParams.count(500);
String cursor = "";
while (!cursor.equals("0")){
ScanResult<String> scanResult=jedis.sscan("testset", cursor, scanParams);
// 返回0 说明遍历完成
cursor = scanResult.getStringCursor();
List<String> result = scanResult.getResult();
long t1 = System.currentTimeMillis();
for(int m = 0;m < result.size();m++){
String element = result.get(m);
jedis.srem("testset", element);
}
long t2 = System.currentTimeMillis();
System.out.println("删除"+result.size()+"条数据,耗时: "+(t2-t1)+"毫秒,cursor:"+cursor);
}
}catch (JedisException e){
e.printStackTrace();
}finally {
if(jedis != null){
jedis.close();
}
}
}
对于其它集合,也有对应的方法。
- hash key:通过hscan命令,每次获取500个字段,再用hdel命令;
- set key:使用sscan命令,每次扫描集合中500个元素,再用srem命令每次删除一个元素;
- list key:删除大的List键,未使用scan命令; 通过ltrim命令每次删除少量元素。
- sorted set key:删除大的有序集合键,和List类似,使用sortedset自带的zremrangebyrank命令,每次删除top 100个元素。
Python脚本批量删除
对于redis的监控和清理,通常会用一些Python脚本去做,简单、轻便。用java的话,再小的一个任务也要打包、发布,如果没有一套完善的开发、发布的流程,还是比较麻烦的。这时候,很多人倾向于写Python脚本,会Python的大部分人都是会Java的。
这里,还是以删除一个set集合为例:
# -*- coding:utf-8 -*- import redis def test():
# StrictRedis创建连接时,这个连接由连接池管理,所以我们无需关注连接是否需要主动释放
re = redis.StrictRedis(host = "0.0.0.0",port = 6379,password = "")
key = "test"
for i in range(100000):
re.sadd(key, i) cursor = ''
cou = 200
while cursor != 0:
cursor,data = re.sscan(name = key, cursor = cursor, count = cou)
for item in data:
re.srem(key, item)
print cursor if __name__ == '__main__':
test()
后台删除之lazyfree机制
为了解决redis使用del命令删除大体积的key,或者使用flushdb、flushall删除数据库时,造成redis阻塞的情况,在redis 4.0引入了lazyfree机制,可将删除操作放在后台,让后台子线程(bio)执行,避免主线程阻塞。
lazy free的使用分为2类:第一类是与DEL命令对应的主动删除,第二类是过期key删除、maxmemory key驱逐淘汰删除。
主动删除
UNLINK命令是与DEL一样删除key功能的lazy free实现。唯一不同时,UNLINK在删除集合类键时,如果集合键的元素个数大于64个(详细后文),会把真正的内存释放操作,给单独的bio来操作。
127.0.0.1:> UNLINK mylist
(integer)
FLUSHALL/FLUSHDB ASYNC 127.0.0.1:> flushall async //异步清理实例数据
被动删除
lazy free应用于被动删除中,目前有4种场景,每种场景对应一个配置参数; 默认都是关闭。
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
slave-lazy-flush no
lazyfree-lazy-eviction
针对redis内存使用达到maxmeory,并设置有淘汰策略时;在被动淘汰键时,是否采用lazy free机制;
因为此场景开启lazy free, 可能使用淘汰键的内存释放不及时,导致redis内存超用,超过maxmemory的限制。此场景使用时,请结合业务测试。
lazyfree-lazy-expire
针对设置有TTL的键,达到过期后,被redis清理删除时是否采用lazy free机制;
此场景建议开启,因TTL本身是自适应调整的速度。
lazyfree-lazy-server-del
针对有些指令在处理已存在的键时,会带有一个隐式的DEL键的操作。如rename命令,当目标键已存在,redis会先删除目标键,如果这些目标键是一个big key,那就会引入阻塞删除的性能问题。 此参数设置就是解决这类问题,建议可开启。
slave-lazy-flush
针对slave进行全量数据同步,slave在加载master的RDB文件前,会运行flushall来清理自己的数据场景,
参数设置决定是否采用异常flush机制。如果内存变动不大,建议可开启。可减少全量同步耗时,从而减少主库因输出缓冲区爆涨引起的内存使用增长。
expire及evict优化
redis在空闲时会进入activeExpireCycle循环删除过期key,每次循环都会率先计算一个执行时间,在循环中并不会遍历整个数据库,而是随机挑选一部分key查看是否到期,所以有时时间不会被耗尽(采取异步删除时更会加快清理过期key),剩余的时间就可以交给freeMemoryIfNeeded来执行。
参考链接:
http://mysql.taobao.org/monthly/2018/10/05/
https://blog.csdn.net/liu1390910/article/details/79728569
https://blog.csdn.net/wsliangjian/article/details/52329320
redis 删除大key集合的方法的更多相关文章
- Redis 的大 Key 对持久化有什么影响?
作者:小林coding 图解计算机基础(操作系统.计算机网络.计算机组成.数据库等)网站:https://xiaolincoding.com 大家好,我是小林. 上周有位读者字节一二面时,被问到:Re ...
- redis删除单个key和多个key,ssdb会落地导致重启redis无法清除缓存
redis删除单个key和多个key,ssdb会落地导致重启redis无法清除缓存,需要针对单个key进行删除 删除单个:del key 删除多个:redis-cli -a pass(密码) keys ...
- redis查找大key
redis中查找出比较大的key 下面直接上代码 (请在测试机上测试) #!/usr/bin/env python import sys import redis def check_big_key( ...
- redis修改大key报Argument list too long的解决办法:
线上一个业务出现异常:redis的一个大大大大大key数据有问题,所以导出修改再导入,但遇到了问题: [root@ ~]# /usr/local/redis/bin/redis-cli -h 127. ...
- redis删除所有key
flushdb 删除当前数据库的所有keyflushall 删除所有数据库的所有keydbsize 返回当前数据库的key的数量
- redis统计大key
–bigkeys redis-cli -h <host> -p <port> -n <db> --bigkeys 这条命令会从指定的 Redis DB 中持续采样, ...
- 【转】linux 下清空或删除大文件的一些方法
原文:https://linux.cn/article-8024-1.html 在 Linux 终端下处理文件时,有时我们想直接清空文件的内容但又不必使用任何 Linux 命令行编辑器 去打开这些文件 ...
- redis过期键删除策略以及大key删除方法
今天遇到了一个前同事挖的坑,刷新缓存中商品信息时先让key过期,然后从数据库里取最新数据然后再放到缓存中,他是这样写的 redisTemplate.expire(CacheConst.GOOGS_PR ...
- Redis大 key的发现与删除方法全解析
个推作为国内第三方推送市场的早期进入者,专注于为开发者提供高效稳定的推送服务,经过9年的积累和发展,服务了包括新浪.滴滴在内的数十万APP.由于我们推送业务对并发量.速度要求很高,为此,我们选择了高性 ...
随机推荐
- Centos7搭建SS以及加速配置的操作记录 (转载)
原文地址https://www.cnblogs.com/kevingrace/p/8495424.html 部署 Shadowsocks之前,对它做了一个简单的了解,下面先介绍下.一道隐形的墙众所周知 ...
- shell脚本学习-练习写一个脚本1
# 1.依次展示/etc/passwd中的用户名和UID.格式如:Hello,$USER,your UID is $UID. # 2.统计一个有多少个用户 #!/bin/bash #Program D ...
- hadoop教程
http://www.yiibai.com/hadoop/hadoop_enviornment_setup.html 改网站讲解详细,还有源码,值得借阅
- JS中的instanceof和typeof,以及特殊引用类型
1.instanceof是用于测试对象类型,通常格式为:a instanceof b,返回true或falise,表示为对象a是否是类型b的实例. typeof则是用于测试基本类型,包括undefin ...
- C语言字符串和十六进制的相互转换方式
C语言的字符串操作并不像java,Csharp那样提供直接的方法,简单粗暴.所以,在转换的时候往往费力费时,近日做项目正好用到和java程序通讯,java发送过来的数据是十六进制数字组成的字符串,解析 ...
- 未能加载文件或程序集“ .....WebUI ”或它的某一个依赖项,试图加载格式不正确的程序
编译Web网站没有问题(需要引用oracle.dataAccess.dll),在运行时报错如下: 解决: 1. 将项目编译生成x86模式(win7 64位) 2. 有可能本机运行有问题,发布到IIS, ...
- 使用@Autowird注入报空指针异常
new的对象不能调用此对象里面注入的其他类,如果想要调用注入的其他类,则此new的对象要使用@componet将此类注入. 原因:
- spring filter lister servlet
https://blog.csdn.net/nacey5201/article/details/8547772 https://blog.csdn.net/xwl617756974/article/d ...
- 11个炫酷的Linux终端命令大全
我已经用了十年的Linux了,通过今天这篇文章我将向大家展示一系列的命令.工具和技巧,我希望一开始就有人告诉我这些,而不是曾在我成长道路上绊住我. 1.命令行日常系快捷键 如下的快捷方式非常有用,能够 ...
- Sqlalchemy python经典第三方orm
Ⅰ. 安装 pip install sqlalchemy Ⅱ. 起步链接 import time import threading import sqlalchemy from sqlalchemy ...