Redis中Key中为什么要使用{}

Redis集群介绍

Redis 集群是一个提供在多个Redis间节点间共享数据的程序集。

Redis集群并不支持处理多个keys的命令,因为这需要在不同的节点间移动数据,从而达不到像Redis那样的性能,在高负载的情况下可能会导致不可预料的错误.

Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令. Redis 集群的优势:

  • 自动分割数据到不同的节点上。
  • 整个集群的部分节点失败或者不可达的情况下能够继续处理命令。

Redis 集群的数据分片

Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念.

Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽.集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:

  • 节点 A 包含 0 到 5500号哈希槽.
  • 节点 B 包含5501 到 11000 号哈希槽.
  • 节点 C 包含11001 到 16384号哈希槽.

这种结构很容易添加或者删除节点. 比如如果我想新添加个节点D, 我需要从节点 A, B, C中得部分槽到D上. 如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可. 由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.

MSET

单实例上的MSET是一个原子性(atomic)操作,所有给定 key 都会在同一时间内被设置,某些给定 key 被更新而另一些给定 key 没有改变的情况,不可能发生。

而集群上虽然也支持同时设置多个key,但不再是原子性操作。会存在某些给定 key 被更新而另外一些给定 key 没有改变的情况。其原因是需要设置的多个key可能分配到不同的机器上。

##SINTERSTORE,SUNIONSTORE,ZINTERSTORE,ZUNIONSTORE

这四个命令属于同一类型。它们的共同之处是都需要对一组key进行运算或操作,但要求这些key都被分配到相同机器上。

这就是分片技术的矛盾之处:

即要求key尽可能地分散到不同机器,又要求某些相关联的key分配到相同机器。

Hash Tags

HashTag机制可以影响key被分配到的slot,从而可以使用那些被限制在slot中操作。

HashTag即是用{}包裹key的一个子串,如{user:}1, {user:}2。

在设置了HashTag的情况下,集群会根据HashTag决定key分配到的slot, 两个key拥有相同的HashTag:{user:}, 它们会被分配到同一个slot,允许我们使用MGET命令。

通常情况下,HashTag不支持嵌套,即将第一个{和第一个}中间的内容作为HashTag。若花括号中不包含任何内容则会对整个key进行散列,如{}user:。

HashTag可能会使过多的key分配到同一个slot中,造成数据倾斜影响系统的吞吐量,务必谨慎使用。

hashtag原理

单实例上的mset、lua脚本等处理多key时,是一个原子性(atomic)操作,所有给定key都会在同一时间内被执行。集群每次通过对key进行hash计算到不同的分片,所以集群上同时执行多个key,不再是原子性操作,会存在某些给定 key 被更新而另外一些给定key没有改变的情况,其原因是需要设置的多个key可能分配到不同的机器上。因此集群引入了hashtag来对多key同时操作,在设置了hashtag的情况下,集群会根据hashtag决定key分配到的slot, 当两个key拥有相同的hashtag时, 它们会被分配到同一个slot。

hashtag使用规则

第一次出现“{”和接下来第一次出现的“}”之间有内容。

例如:

  • 这两个键{user1000}.following和{user1000}.followers由于只有一对{},将user1000来计算hash。
  • 对于键foo{}{bar},整个键foo{}{bar}将像往常一样计算hash,因为第一次出现的“{”后面跟“}”中间没有字符。
  • 对于键foo{{bar}}zap,子字符串{bar将被计算hash,因为它是第一次出现“{”和第一次出现“}”之间的子字符串。
  • 对于键foo{bar}{zap}的子字符串bar将被计算hash,因为只使用第一个“{”和“}”。

hashtag用法示例

当如下操作时:

EVAL "redis.call('set',KEYS[1],ARGV[1]) redis.call('set',KEYS[2],ARGV[2])" 2 key1 key2 value1 value2

出现以下报错:

ERR 'key1' and 'key2' not in the same slot

可通过hashtag进行解决:

EVAL "redis.call('set',KEYS[1],ARGV[1]) redis.call('set',KEYS[2],ARGV[2])" 2 {user}key1 {us

 

posted @   Boblim  阅读(653)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-08-02 解析json之net.sf.json
2021-08-02 在阻塞式io中,如果一个线程在等待io操作,那么cpu还会分配时间片给该线程吗?
2017-08-02 java中的char占几个字节
点击右上角即可分享
微信分享提示