比如现在redis有3个集群分片(A、B、C),
有一个高频热点key,保存在分片A上,会导致请求的倾斜,使得A分片的读取压力过大。
现在希望将key设计成:key1、key2、key3,都对应相同的value
存储的时候:
key1存在分片A
key2存在分片B
key3存在分片C
查询的时候:
key随机转化成key1、key2、key3的其中一个,然后路由到某个分片上。
key1、key2、key3的值改怎么设计?
开发人员怎么知道一个key对应的哈希值是多少
比如现在redis有3个集群分片(A、B、C),
有一个高频热点key,保存在分片A上,会导致请求的倾斜,使得A分片的读取压力过大。
现在希望将key设计成:key1、key2、key3,都对应相同的value
存储的时候:
key1存在分片A
key2存在分片B
key3存在分片C
查询的时候:
key随机转化成key1、key2、key3的其中一个,然后路由到某个分片上。
key1、key2、key3的值改怎么设计?
开发人员怎么知道一个key对应的哈希值是多少
应用层解决方法:
ORIGINAL_KEY="some_hot_key"
VALUE="some_value"
KEY_SUFFIXES=(1 2 3)
KEYS=()
for SUFFIX in "${KEY_SUFFIXES[@]}"; do
KEY="${ORIGINAL_KEY}_${SUFFIX}"
SLOT=$(redis-cli CLUSTER KEYSLOT "$KEY")
echo "Key $KEY is in slot $SLOT."
KEYS+=("$KEY")
done
# 存储值到所有键
for KEY in "${KEYS[@]}"; do
redis-cli SET "$KEY" "$VALUE"
done
SELECTED_KEY=${KEYS[$RANDOM % ${#KEYS[@]}]}
VALUE=$(redis-cli GET "$SELECTED_KEY")
echo "The value of $SELECTED_KEY is '$VALUE'."
你可以这样弄,比如redis key 为 recommend,总共分3片,你 recommend-1,recommend-2,recommend-3, 你redis set的时候,同时 set 这三个key, get 时
// 伪代码
getRecommend(){
// 先随机出1-3一个数
Random random = new Random();
int randomNumber = random.nextInt(3) + 1;
// 然后就可以随机出个key取值了
String cacheKey = "recommend-"+ randomNumber;
}
3 回答4.1k 阅读✓ 已解决
4 回答1.9k 阅读
1 回答768 阅读✓ 已解决
2 回答1.3k 阅读
3 回答635 阅读
最近看了一下docker搭建redis集群的知识,我来自己回答一下这个问题吧。
哈希槽原理
首先redis cluster会创建[0,16383]哈希槽,供多个集群分片使用。
当set Key Value保存数据时,redis会使用★【CRC16算法】★,计算key的hash值。
具体公式 : 槽位 = CRC16.crc16(key) % 16384
后缀拼接序号方案(行不通)
所以直接在将key拼接数字后缀,形成key-1,key-2,key-3,最终形成的hash并不能保证分别落在不同的分区哈希槽上,来降低热点数据key在单个节点的负载。参考如下代码:
综上,通过key拼接数字后缀并不能在redis集群模式下,实现副本key在多个节点上的平均分布。
其他解决方案:
【方案1】引入额外的redis服务单独存储热点数据
此时:
【方案2】本地缓存法(即二级缓存)
直接使用本地缓存,比如ehcache,当读取高频热点数据时,直接内存中读取。可以设置较短的过期时间,只要数据一直高频访问,就不会过期。在高频读取场景下,节省了reids的网络io成本,更推荐