背景:某提醒服务在压测时,redis集群出现了热点key问题,qps倾斜严重。
热点key对应的category为metric_msgType_day_push_id,生成key的代码和category的参数配置如下,
public static StoreKey genMetricPushIdCacheKey(MsgTypeEnum msgTypeEnum, String updateDay) {
return new StoreKey(METRIC_PUSH_ID_CACHE_KEY, msgTypeEnum.getValue(), updateDay);
}
原因分析:
该热点key的生成,由消息类型msgTypeEnum.getValue()和日期updateDay决定,squirrel对应的finalKey的结构为,${category}.${template}_${version} ,template即为m{0}d{1},
如果在某一天的一段时间内,某类消息大量发送(如发送量最大的点评push通道消息),此时最终的key为metric_msgType_day_push_id.mdpCommonPushd20211219_0。
key在redis中的存储
redis对key进行读写时,会根据key的hash计算出对应的哈希槽(slot,哈希槽共16384个)。一个redis节点会负责一个或多个slot,对该key的请求会全部落在该redis节点上,导致流量倾斜严重。
squirrel会从category层面上对热key进行限流,造成category不可用。
解决方案
原key由msgType和day组成,现在key修改为由msgType、day和一个随机数组成,随机数范围为[0,12]。取某个消息类型(msgType)在当日(day)的value(缓存的pushId)时,从0-12开始遍历,返回这12个key对应的全体pushId










