前者主要表示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进程数十秒。所以本文只从时间复杂度分析大的集合类键。删除这种大键的风险,以及怎么优雅地删除。
说明:本文删除大key的方法,只适用于支持scan命令的Redis2.8+版本
在Redis集群中,应用程序尽量避免使用大键;直接影响容易导致集群的容量和请求出现”倾斜问题“,具体分析见文章: redis-cluster-imbalance
直接删除大key的风险DEL命令在删除单个集合类型的Key时,命令的时间复杂度是O(M) M是集合类型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阻塞,出现故障切换和访问Redis的应用程序雪崩的情况。
测试删除集合类型大Key耗时,一般每秒可清理10w~数十w个元数; 如果数百w个元素的大key时,会导致Redis阻塞上10秒
可能导致集群判断Redis已经故障,出现故障切换;或应用程序没有fast fail机制,出现雪崩的情况。
当我们发现集群中有大key时,要删除时,如何youya地处理呢?
如何优ya地删除各类大key从Redis2.8版本开始支持 SCAN 命令,通过m次时间复杂度为O(1)的方式,遍历包含n个元素的大key.
这样避免单个O(n)的大命令,导致Redis阻塞。 这里删除大key操作的思想也是如此。