有两个原因:
一个是实例上的Slot数据分配不均匀;存在bigKey,存储了大量集合元素或本身就很大(String)。
大Key应对办法:
- 业务层避免一个key中存储大量元素;
- 如何是集合类型元素,则尽量拆分成多个小的集合中,保存在不同的实例上去。
热点Key解决办法
解决方案一: 备份热key
可以把热点数据备份多份,在每个随机副本中给key添加一个随机后缀,尽量存储在不同的实例中去,访问的时候同样给key添加随机后缀,这样就可以将流量分散到不同的实例中去。
解决方案 二: 本地缓存+动态计算自动发现热点缓存*
主动发现热点key,对其进行存储。
首先 Client 也会访问 SLB,并且通过 SLB 将各种请求分发至 Proxy 中,Proxy 会按照基于路由的方式将请求转发至后端的 Redis 中。
在热点 key 的解决上是采用在服务端增加缓存的方式进行。具体来说就是在 Proxy 上增加本地缓存,本地缓存采用 LRU 算法来缓存热点数据,后端节点增加【热点数据计算模块】来返回热点数据。
Proxy 架构的主要有以下优点:
- Proxy 本地缓存热点,读能力可水平扩展
- DB 节点定时计算热点数据集合
- DB 反馈 Proxy 热点数据
- 对客户端完全透明,不需做任何兼容
对热点key的监控:
可以使用zk集群对热点key进行监控,然后所有本地节点监听该热点数据,然后加载到本地缓存中去。
最后由于 proxy 是可以水平扩充的,因此可以任意增强热点数据的访问能力。
最佳成熟方案之一 : JD开源hotKey
这是目前较为成熟的自动探测热key、分布式一致性缓存解决方案。原理就是在client端做洞察,然后上报对应hotkey,server端检测到后,将对应hotkey下发到对应服务端做本地缓存,并且能保证本地缓存和远程缓存的一致性。
1 客户端引用HotKey的client,将自己的信息上报给worker,和worker之间建立长链接,定时拉取热点key的规则和woker的集群信息。
2 通过计算isHot()计算出哪些key需要上报。
3 通过定时任务将热点key上报给worker。
4 woker计算出确实是热点key后,则推送给所有客户端,进行本地缓存。
源码详解:
相关链接: