Redis BigKey 的处理和隐患

什么是 BigKey

误区:BigKey 并不是指的key 很大,而是value很大

为什么会产生这种情况?
:一般来说,key是由我们代码指定的,比如 uid + “:” + orderid,所以 key 的大小是可以预估出来的,不会太大。而value是要写入的值,不是受代码去控制的,可能会导致value很大大情况发生

发生的场景
音乐歌单的情况,用户和歌单的映射关系储存在Redis当中,通常情况下,一个歌单可能被多个用户去订阅,也就是一对多的情况,需要用一个list去储存用户id

  • 所以 key:歌单id value:用户id列表
  • 但是当订阅的用户很多的时候,就会不可控,用户id列表可能会很大,几万、几十万,也就发生了大Key问题
    在这里插入图片描述

redis常用数据结构对大key的定义

  • value 是 String 类型, size 超过 10KB
  • value 是 ZSet、Hash、List、Set等集合类型时,它的成员数量超过 1w 个

ps:定义并不是绝对的

BigKey 有什么影响

内存空间分布不均匀

这样不利于集群对内存的统一管理,存在丢失数据的隐患

超时阻塞

由于 Redis 单线程的 特性,操作 bigkey也就意味着更加的耗时,使 Redis 阻塞的可能性就越大,就有可能造成客户端阻塞或者引起故障切换,因为查询过慢

网络阻塞

bigkey数据大,也就导致网络传输数据流量大,就有可能会造成网络阻塞,影响其他的服务

bigkey删除

由于数据量大,而redis的 DEL命令在删除的时候,时间复杂度是 O(M),M是key包含的个数,这就有可能导致Redis堵塞在删除这一步,和上面超时阻塞的情况同样的结果

DEL keyTime 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).

所以应当避免在生产环境情况下去删除bigkey,否则很有可能导致阻塞

测试删除集合类型大Key耗时,一般每秒可清理 100 w ~ 数百万元素,如果出现上千万元素,就可能导致Redis阻塞若干秒,导致哨兵或集群等认为 Redis 发生故障,从而发生故障转移

小于4.0版本可以使用游标迭代器SCAN,将时间复杂度降低为 O(1),分散为 m 次时间复杂度 O(1)的操作,也就避免了长时间阻塞删除的情况发生,让Redis能够切换其他命令运行

在 Redis 4.0 后,引入了lazyfree,也就是异步删除,将删除操作放在后台, 让后台子线程执行,避免主进程阻塞

要注意:引入了 lazyfree 后,DEL命令依旧是同步阻塞的,异步的是 FLUSHALL/FLUSHDB 或者是驱逐淘汰策略中的被动删除

如何找到BigKey

  • 增加流量监控、超时、内存等指标监控
  • bigkeys命令
    • 遍历 redis 中所有key,返回整体的统计信息和每个数据类型 top1 的大小
  • 图形化工具

如何解决BigKey问题

首先要了解是如何产生的bigkey,往往是业务方案设计的不合理,没有预见到 value 的动态增长问题:

  • 一直往 value 中新增数据,没有删除机制
  • 数据没有合理分片

如何去解决bigkey

键值设计

key

  • 可读性和可管理性,比如 业务名:表名:id
  • 简洁性,保证语义的情况下减少字符,比如 userid:{uid} 简化为 u:{uid}
  • 不要包含特殊字符

value

  • 避免设置 bigkey
    在Redis中,一个字符串最大512MB,一个二级数据结构(例如hash、list、set、zset)可以存储大约40亿个(2^32-1)个元素,但实际中如果下面两种情况,我就会认为它是bigkey。

  • 字符串类型

    • 它的big体现在单个value值很大,一般认为超过10KB就是bigkey。
  • 非字符串类型:(hash,list,set,zset等)

    • 哈希、列表、集合、有序集合,它们的big体现在元素个数太多。
      一般来说hash、list、set、zset元素个数不要超过5000。

优化 BigKey

  1. 大拆小
    比如 hash 结构中有 100万 的数据拆分成 200 个 key,每个 key 中存放 5000条数据
  2. 避开危险操作
    主要是 O(N) 复杂度的操作,比如 hgetall
  3. 合理控制生命周期,过期性

资料来源

redis之bigkey
解决了Redis大 key 问题
Redis 的大 Key 对持久化有什么影响?
JAVA必学:Redis BigKey

猜你喜欢

转载自blog.csdn.net/DespairC/article/details/126834620