`
m635674608
  • 浏览: 5031156 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

如何优雅地删除Redis大键

 
阅读更多

关于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版本和负载等因素有关

Key类型 Item数量 耗时
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

分享到:
评论

相关推荐

    redis常用文档(自己总结的)

    ### Redis键操作 #### 基础操作 - `del key`:删除键`key`。 - `exists key`:检查键`key`是否存在。 - `set key value`:设置键`key`的值为`value`。 - `get key`:获取键`key`的值。 - `keys pattern`:查找匹配...

    本地Redis.rar

    6. **关闭Redis**:在命令行客户端输入`SHUTDOWN`命令,优雅地关闭Redis服务。 7. **生产环境注意事项**:在生产环境中,通常会配置Redis作为后台服务自动启动,并通过防火墙设置只允许特定IP访问,以增强安全性。 ...

    spring-data-redis 1.7.6

    7. **事件监听**:Spring Data Redis支持事件监听,可以监听Redis中的某些操作(如键的创建、删除等),并在应用程序中进行相应的处理。 8. **脚本支持**:通过`ScriptOperations`,开发者可以执行Lua脚本,这在...

    Redis-x64.3.0

    - 通过`redis-cli -p 端口号 shutdown`命令可以优雅地关闭Redis服务。 - Windows服务安装:可以创建一个系统服务,让Redis随系统启动,便于管理和维护。 6. **性能优化**: - 调整内存分配器,例如使用jemalloc...

    redis工具包

    3. 执行命令:使用客户端提供的API执行Redis命令,例如设置键值对、获取值、删除键等。 4. 高级操作:利用客户端支持的高级功能,如事务、管道、发布/订阅、分布式锁等。 5. 关闭连接:在完成操作后,记得关闭...

    php操作redis封装的类.zip

    2. 键操作:封装基本的键值操作,如`set`用于设置键值,`get`用于获取键值,`delete`用于删除键,`exists`检查键是否存在,以及`keys`获取所有匹配模式的键。 3. 数据结构操作:对应Redis的数据结构,封装方法如`...

    redis操作工具类

    在本项目中,我们将探讨如何在Spring Boot中优雅地集成Redis,并利用工具类进行高效的操作。 首先,集成Redis到Spring Boot应用中,我们需要在`pom.xml`或`build.gradle`中添加Redis的依赖,例如使用Spring Data ...

    Redis如何优雅的删除特定前缀key

    本文将详细介绍如何在 Redis 中优雅地删除特定前缀的键,并讨论 `SCAN` 命令的使用。 首先,我们需要理解为什么不能直接使用 `keys` 命令。`keys` 命令会遍历整个数据库,查找匹配模式的所有键,如果数据库中的键...

    Spring Redis缓存实例

    Spring框架提供了一种优雅的方式来整合缓存管理,其中包括对Redis的支持。Redis是一个开源的、高性能的键值数据库,常用于数据缓存、消息队列等多种场景。本文将详细介绍如何使用Spring集成Redis来实现数据缓存。 #...

    redis3.0和redis-desktop-manager

    5. **Keyspace通知(Keyspace Notifications)**:这是一个新特性,允许Redis服务器向客户端发送有关键操作的通知,比如键的过期、删除或更新,这为开发实时监控和日志记录等功能提供了便利。 6. **jemalloc内存...

    Redis测试程序

    测试程序中应包含适当的异常处理机制,确保在遇到网络错误或其他问题时能够优雅地处理。同时,记录日志可以帮助开发者跟踪和调试程序运行时的问题。 7. **性能测试** 对于Redis这类高性能系统,性能测试是必不可...

    基于java的使用Redis存放Session RedisManager.zip

    通常,Session ID会作为Redis键的一部分,如`session:` + `sessionId`。 5. **过期策略**:Redis支持设置过期时间,项目可能利用这一特性为每个Session设置生命周期。当Session超时,Redis中的相应键会自动删除,...

    redis-2.1.0 和commons-pool-1.5.6 Java测试redis values 类型

    5. **异常处理**: 在测试代码中,还需要考虑异常处理,如网络异常、超时异常等,确保程序在出现问题时能够优雅地处理并给出反馈。 6. **事务操作**: Redis支持简单的事务(Multi、Exec),测试代码可能会涉及如何在...

    前端开源库-swint-redis-cache

    4. **错误处理**:内置错误处理机制,当 Redis 服务出现问题时,能够优雅地处理异常,避免程序崩溃。 5. **性能优化**:通过 Redis 的高速缓存能力,提高前端应用的数据读取速度,改善用户体验。 ### 安装与使用 ...

    Redis的配置、启动、操作和关闭方法

    Redis是一款高性能的键值存储系统,常用于缓存...确保正确关闭Redis服务至关重要,因为它涉及到数据一致性以及资源的优雅释放。在生产环境中,应当遵循最佳实践来管理和操作Redis实例,确保系统的稳定性和数据安全性。

    golang实现Redis分布式自旋锁+本地自旋锁

    在实际应用中,需要对这些异常进行处理,确保系统在出现问题时能够优雅地恢复。 6. **上下文管理**: `context.Context`对象在`SpinLockUntilTimeOut`函数中被使用,允许外部在需要时取消锁的获取过程,防止无休止...

    用注解实现redis分布式锁,防止短时间内重复请求

    总的来说,通过注解实现Redis分布式锁是一种高效且易于维护的方式,它能够帮助我们优雅地处理并发问题,确保短时间内不会出现重复请求,从而提高系统的稳定性和性能。结合Spring的AOP特性,我们可以将锁的管理逻辑与...

    ruby安装包下载 - ruby环境搭建

    # 删除键 redis.del('key') ``` 通过这种方式,Ruby和Redis的结合,为开发者提供了高效、可扩展的数据存储和处理解决方案。 总结起来,搭建Ruby环境涉及下载和安装Ruby、设置Gem环境以及管理项目依赖。同时,Ruby...

    cache-it:一个简单的用于nodejs的缓存模块,基于redis构建

    6. **错误处理**:良好的错误处理机制,确保在Redis连接出现问题时,仍能优雅地处理请求。 **使用步骤** 1. **安装**:首先,需要在项目中安装`cache-it`模块,通常使用npm进行安装:`npm install cache-it`。 2. ...

    Ruby-OhmRedis的Objecthash映射库

    Ohm属于后者,它提供了Ruby对象和Redis数据结构之间的直接映射,使得开发人员可以方便地使用Ruby的面向对象编程特性来操作Redis。 Ohm的核心概念包括模型(Model)、键(Key)和集合(Set)。模型是Ruby类,它们...

Global site tag (gtag.js) - Google Analytics