python引入redis_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:6380> info memory
# Memory
used_memory:15175740016
used_memory_human:14.13G
used_memory_rss:22302339072
used_memory_peak:22351749192
used_memory_peak_human:20.82G
used_memory_lua:36864
mem_fragmentation_ratio:1.47
mem_allocator:jemalloc-3.6.0
10.1.254.18:6380> scard helper_2019-03-12
(integer) 64530980
10.1.254.18:6380> del helper_2019-03-12
(integer) 1
(81.23s)
10.1.254.18:6380> info memory
# Memory
used_memory:8466985704
used_memory_human:7.89G
used_memory_rss:10669453312
used_memory_peak:22351749192
used_memory_peak_human:20.82G
used_memory_lua:36864
mem_fragmentation_ratio:1.26
mem_allocator:jemalloc-3.6.0
可以看到,helper_2019-03-12这个key,是一个包含64530980个元素的集合,直接使用del删除命令,花的时间为:81.23s,在超时时间短的苛刻情况下,显然会发送超时,程序异常!好在,我们用的是连接池,没有出现问题。
分批删除
这种情况,应该使用sscan命令,批量删除set集合元素的方法。下面是一个java的例子:
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 redisdef test():# StrictRedis创建连接时,这个连接由连接池管理,所以我们无需关注连接是否需要主动释放re = redis.StrictRedis(host = "0.0.0.0",port = 6379,password = "123")key = "test"for i in range(100000):re.sadd(key, i)cursor = '0'cou = 200while cursor != 0:cursor,data = re.sscan(name = key, cursor = cursor, count = cou)for item in data:re.srem(key, item)print cursorif __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:7000> UNLINK mylist
(integer) 1
FLUSHALL/FLUSHDB ASYNC
127.0.0.1:7000> 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来执行。
参考链接:
Redis · lazyfree · 大key删除的福音
https://blog.csdn.net/liu1390910/article/details/79728569
https://blog.csdn.net/wsliangjian/article/details/52329320
python引入redis_redis 删除大key集合的方法相关推荐
- Redis删除大Key
原文链接:https://www.dubby.cn/detail.html?id=9112 这里说的大key是指包含很多元素的set,sorted set,list和hash. 删除操作,我们一般想到 ...
- redis bigkey 解决 删除大key
大Key会带来的问题 如果是集群模式下,无法做到负载均衡,导致请求倾斜到某个实例上,而这个实例的QPS会比较大,内存占用也较多:对于Redis单线程模型又容易出现CPU瓶颈,当内存出现瓶颈时,只能进行 ...
- Python list列表删除元素(4种方法)
文章目录 Python list列表 del:根据索引值删除元素 pop():根据索引值删除元素 remove():根据元素值进行删除 clear():删除列表所有元素 Python list列表 在 ...
- 4.4 Python list列表删除元素(4种方法
在 Python 列表中删除元素主要分为以下 3 种场景: 根据目标元素所在位置的索引进行删除,可以使用 del 关键字或者 pop() 方法: 根据元素本身的值进行删除,可使用列表(list类型)提 ...
- python基础之删除文件及删除目录的方法
下面来看一下python里面是如何删除一个文件及文件夹的~~ #首先引入OS模块 import os #删除文件: os.remove() #删除空目录: os.rmdir() #递归删除空目录: o ...
- python关闭浏览器删除session_Django操作session 的方法
session是存放在服务端的,在django中使用session必须要先在数据库中创建django_session表,session相关信息都要依赖此表 获取session request.sess ...
- redis中有key但是删不掉_Redis大 key的发现与删除方法全解析
个推作为国内第三方推送市场的早期进入者,专注于为开发者提供高效稳定的推送服务,经过9年的积累和发展,服务了包括新浪.滴滴在内的数十万APP.由于我们推送业务对并发量.速度要求很高,为此,我们选择了高性 ...
- redis中有key但是删不掉_Redis大key的发现与删除方法全解析
个推作为国内第三方推送市场的早期进入者,专注于为开发者提供高效稳定的推送服务,经过9年的积累和发展,服务了包括新浪.滴滴在内的数十万APP.由于我们推送业务对并发量.速度要求很高,为此,我们选择了高性 ...
- php redis hash删除key,如何优雅的删除Redis的大key
关于Redis大键(Key),我们从[空间复杂性]和访问它的[时间复杂度]两个方面来定义大键.前者主要表示Redis键的占用内存大小:后者表示Redis集合数据类型(set/hash/list/sor ...
最新文章
- 网站实现个人支付宝即时到帐POST页面
- Python编程语言学习:python的列表的特殊应用之一行命令实现if判断中的两类判断
- JavaFX控制器:设置按钮点击事件代码示例
- html盒子模型子元素怎么水平占满父元素_CSS3——弹性盒模型-flex——父级属性...
- Codeforces Round #717 (Div. 2)
- RTree算法及介绍
- 强大实用的DISM命令
- 【推荐】.NET批量上传控件——HtmlInputFiles
- svn linux版本下载,linux 下安装 subversion(svn) 客户端
- rocketmq底层通信模块解析
- linux查看网卡带宽命令,Linux查看网卡带宽的两个命令
- 是时候让打字更“快舒”了-小鹤双拼
- uniapp中text-indent不起作用,uniapp首行缩进不管用如何解决?
- AI challenger 2018图片分类比赛—农作物病害检测
- 长歌行 宋 郭茂倩收编的《乐府歌词》汉代民间诗歌
- 锐龙4750u和4800u的区别
- 不懂就学——什么是input和output?
- Zookeeper——Watcher原理详解
- Python代码:检查学号是否合法
- 3G上网卡2_编程自动切换模式学习笔记
热门文章
- Spring Security 入门(五):在 Spring-Boot中的应用
- yii2 mysql gone away,yii2 console MySQL server
- CSS样式----块级元素和行内元素
- 视频防抖 Opencv
- pyqt改变背景颜色
- module 'paddle.fluid' has no attribute 'data'
- 在VS2015中使用Boost库
- 'utf-8' codec can't decode byte 0xb6 in position 34: invalid start byte
- 43 inventory文件
- 渗透测试-getshell方法总结