关于Redis大键(Key),我们从[空间复杂性]和访问它的[时间复杂度]两个方面来定义大键。
前者主要表示redis键的占用内存大小;后者表示Redis集合数据类型(set/hash/list/sorted set)键,所含有的元素个数。以下两个示例:
1个大小200MB的String键(String Object最大512MB);内存空间角度占用较大
1个包含100000000(1kw)个字段的Hash键,对应访问模式(如hgetall)时间复杂度高
因为内存空间复杂性处理耗时都非常小,测试 del 200MB String键耗时约1毫秒,
而删除一个含有1kw个字段的Hash键,却会阻塞Redis进程数十秒。所以本文只从时间复杂度分析大的集合类键。删除这种大键的风险,以及怎么优雅地删除。
在Redis集群中,应用程序尽量避免使用大键;直接影响容易导致集群的容量和请求出现”倾斜问题“,具体分析见文章:redis-cluster-imbalance。但在实际生产过程中,总会有业务使用不合理,出现这类大键;当DBA发现后推进业务优化改造,然后删除这个大键;如果直接删除它,DEL命令可能阻塞Redis进程数十秒,对应用程序和Redis集群可用性造成严重的影响。
直接删除大Key的风险
DEL命令在删除单个集合类型的Key时,命令的时间复杂度是O(M),其中M是集合类型Key包含的元素个数。
DEL key
Time complexity: O(N) where N is the number of keys that will be removed. When a key to remove holds a value other than a string, the individual complexity for this key is O(M) where M is the number of elements in the list, set, sorted set or hash. Removing a single key that holds a string value is O(1).
生产环境中遇到过多次因业务删除大Key,导致Redis阻塞,出现故障切换和应用程序雪崩的故障。
测试删除集合类型大Key耗时,一般每秒可清理100w~数百w个元素; 如果数千w个元素的大Key时,会导致Redis阻塞上10秒
可能导致集群判断Redis已经故障,出现故障切换;或应用程序出现雪崩的情况。
说明:Redis是单线程处理。
单个耗时过大命令,导致阻塞其他命令,容易引起应用程序雪崩或Redis集群发生故障切换。
所以避免在生产环境中使用耗时过大命令。
Redis删除大的集合键的耗时, 测试估算,可参考;和硬件环境、Redis版本和负载等因素有关
Hash | ~100万 | ~1000ms |
List | ~100万 | ~1000ms |
Set | ~100万 | ~1000ms |
Sorted Set | ~100万 | ~1000ms |
当我们发现集群中有大key时,要删除时,如何优雅地删除大Key?
如何优雅地删除各类大Key
从Redis2.8版本开始支持SCAN命令,通过m次时间复杂度为O(1)的方式,遍历包含n个元素的大key.
这样避免单个O(n)的大命令,导致Redis阻塞。 这里删除大key操作的思想也是如此。
Delete Large Hash Key
通过hscan命令,每次获取500个字段,再用hdel命令,每次删除1个字段。
Python代码:
1
2
3
4
5
6
7
8
|
def del_large_hash():
r = redis.StrictRedis(host='redis-host1', port=6379)
large_hash_key ="xxx" #要删除的大hash键名
cursor = '0'
while cursor != 0:
cursor, data = r.hscan(large_hash_key, cursor=cursor, count=500)
for item in data.items():
r.hdel(large_hash_key, item[0])
|
Delete Large Set Key
删除大set键,使用sscan命令,每次扫描集合中500个元素,再用srem命令每次删除一个键
python代码:
1
2
3
4
5
6
7
8
|
def del_large_set():
r = redis.StrictRedis(host='redis-host1', port=6379)
large_set_key = 'xxx' # 要删除的大set的键名
cursor = '0'
while cursor != 0:
cursor, data = r.sscan(large_set_key, cursor=cursor, count=500)
for item in data:
r.srem(large_size_key, item)
|
Delete Large List Key
删除大的List键,未使用scan命令; 通过ltrim命令每次删除少量元素。
Python代码:
1
2
3
4
5
|
def del_large_list():
r = redis.StrictRedis(host='redis-host1', port=6379)
large_list_key = 'xxx' #要删除的大list的键名
while r.llen(large_list_key)>0:
r.ltrim(large_list_key, 0, -101) #每次只删除最右100个元素
|
Delete Large Sorted set key
删除大的有序集合键,和List类似,使用sortedset自带的zremrangebyrank命令,每次删除top 100个元素。
Python代码:
1
2
3
4
5
|
def del_large_sortedset():
r = redis.StrictRedis(host='large_sortedset_key', port=6379)
large_sortedset_key='xxx'
while r.zcard(large_sortedset_key)>0:
r.zremrangebyrank(large_sortedset_key,0,99)#时间复杂度更低 , 每次删除O(log(N)+100)
|
Redis Lazy Free
应该从3.4版本开始,Redis会支持lazy delete free的方式,删除大键的过程不会阻塞正常请求。
参考:
lazy redis
issue 1748
Delete Large Hash
http://blog.csdn.net/wsliangjian/article/details/52329320
相关推荐
redisredis redis redis redis
Windows 上安装 Redis安装Windows 上安装 Redis安装Windows 上安装 Redis安装Windows 上安装 Redis安装Windows 上安装 Redis安装Windows 上安装 Redis安装Windows 上安装 Redis安装Windows 上安装 Redis安装Windows ...
主要介绍了Redis中统计各种数据大小的方法,本文使用PHP实现统计Redis内存占用比较大的键,需要的朋友可以参考下
Redis实战 Redis实战 Redis实战 Redis实战 Redis实战 Redis实战 Redis实战
Redis 思维导图 Redis Redis Redis
redis消息体的大小对性能的影响测试报告
如何优雅的使用Redis呢?来回实体,能智能序列化,完全不手动添加代码,优雅的一批,demo已经写好,拿出show吧
很好地redis管理软件 redis client
shell脚本写的删除redis中所有特殊键值的脚本。也可以修改一下自动操作redis
其中最常用的是redis-windows,它是一个Windows下的Redis管理工具,可以方便地安装、配置和管理Redis服务器。 redis-windows提供了一个简单易用的界面,可以让用户轻松地启动、停止和重启Redis服务器,以及管理...
linux系统下,模糊匹配,可批量删除redis的key,修改ip即可使用。试用场景:redis内存爆满、redis不能定时清理数据等。
Redis Desktop Manager(简称RDM)是一款跨平台的Redis数据库管理工具,它提供了一个直观且用户友好的图形界面,允许开发者和运维人员轻松地连接到Redis服务器,并对其进行管理和操作。通过Redis Desktop Manager,...
redis 安装包redis 安装包redis 安装包redis 安装包redis 安装包redis 安装包
redis缓存 redis缓存
Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装Redis3集群安装...
redis6.2.6 redis.conf配置文件
redis redisDesktop ---------安装redis及使用redisDesktop查看数据
redis安装 1: 下载redis-5.0.4.tar.gz 2: 解压源码并进入目录 tar zxvf redis-5.0.4.tar.gz cd redis-5.0.4 3: 不用configure 4: 直接make (如果是32位机器 make 32bit) 查看linux机器是32位还是64位的方法:...
RedisClient将redis数据以资源管理器的界面风格呈现给用户,可以帮助redis开发人员和维护人员方便的建立,修改,删除,查询redis数据,完全不需要了解redis命令。可以让用户方便的编辑数据,可以剪切,拷贝,粘贴...
查找给定键的复杂度为 O(1) ,对键进行序列化的复杂度为 O(N*M) ,其中 N 是构成 key 的 Redis 对象的数量,而 M 则是这些对象的平均大小。 如果序列化的对象是比较小的字符串,那么复杂度为 O(1) 。 返回值: 如果 ...