我应该怎么用我的Redis(四)? | 青训营

132 阅读3分钟

注意的问题

大 Key,热 Key

数据类型大Key标准
String类型Value的字节数大于10KB即为大Key
Hash/Set/ZSet/List等复杂结构类型元素个数大于5000个或总Value字节数大于10MB即为大Key

执行过程

大Key消除方法

  • 拆分:将一个大 Key 拆分成多个小的 Key,例如一个 String 拆分成多个 String
  • 压缩:将压缩后的 Value 写入 Redis,读取的时候再使用。但是需要注意的是压缩算法可能会带来一定的耗时,需要先进行对应的测试
  • 集合类的结构:
    • 拆分:使用 Hash 取余,位掩码决定放在哪个 Key 中。
    • 区分冷热:例如我们可以把热点数据(评论前10页)写入 Redis,后续走 DB

热Key消除方法

定义

用户访问一个Key的QPS特别高,导致Server实例出现CPU负载突增或者不均的情况。热key没有明确的标准,QPS 超过500就有可能被识别为热 Key。

热Key

解决方案

设置Localcache

在访问 Redis 前,在业务服务侧设置 Localcache,降低访问 Redis 的 QPS 。 LocalCache 中缓存过期或未命中,则从 Redis 中将数据更新到 LocalCache 。Java 的 Guava、Golang 的 Bigcache 就是这类 LocalCache。

LocalCache

拆分

将 key:value 这一个热 Key 复制写入多份,例如 key1:value,key2:value ,访问的时候访问多个 key,但 value 是同一个,以此将 QPS 分散到不同实例上,降低负载。代价是,更新时需要更新多个 key,存在数据短暂不一致的风险

热Key拆分转存失败,建议直接上传图片文件

热Key承载

Redis 代理

慢查询

  • 批量操作一次性传入过多的 key/value,如 mset/hmset/sadd/zadd 等 O(n) 操作 建议单批次不要超过100,超过100之后性能下降明显。
  • zset 大部分命令都是 O(log(n)),当大小超过 5k 以上时,简单的 zadd/zrem 也可能导致慢查询
  • 操作的单个 value 过大,超过 10KB。也即,避免使用大 Key
  • 对大 key 的 delete/expire 操作也可能导致慢查询,Redis4.0 之前不支持异步删除 unlink,大 key 删除会阻塞 Redis

缓存穿透、缓存雪崩

缓存穿透:热点数据查询绕过缓存,直接查询数据库 缓存雪崩:大量缓存同时过期

缓存穿透的危害

  • 查询一个一定不存在的数据:通常不会缓存不存在的数据,这类查询请求都会直接打到db,如果有系统bug或人为攻击,那么容易导致db响应慢甚至宕机。
  • 缓存过期时:在高并发场景下,一个热key如果过期,会有大量请求同时击穿至db,容易影响db性能和稳定。同一时间有大量key集中过期时,也会导致大量请求落到db上,导致查询变慢,甚至出现db无法响应新的查询。

解决缓存穿透

  • 缓存空值:如一个不存在的userID。这个id在缓存和数据库中都不存在。则可以缓存一个空值,下次再查缓存直接反空值。
  • 布隆过滤器:通过bloom filter算法来存储合法Key,得益于该算法超高的压缩率,只需占用极小的空间就能存储大量key值。

解决缓存雪崩

  • 缓存空值:将缓存失效时间分散开。
  • 使用缓存集群,避免单机宕机造成的缓存雪崩。