#yyds干货盘点#【Redis集群原理专题】分析一下相关的Redis服务分片技术和Hash Tag

2022年01月16日 阅读数:3
这篇文章主要向大家介绍#yyds干货盘点#【Redis集群原理专题】分析一下相关的Redis服务分片技术和Hash Tag,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

背景介绍

Redis 集群没有使用一致性hash,而是引入了哈希槽的概念,预分好16384个桶,根据 CRC16(key) mod 16384的值,决定将一个key放到哪一个桶中,每一个Redis物理结点负责一部分桶的管理,当发生Redis节点的增减时,调整桶的分布便可。算法

Hash tag的使用背景

场景1

为了实现将key分到相同机器,就须要相同的hash值,即相同的key,但key相同是不现实的,由于key都有不一样的用途。ide

Hash tag实际案例

例如:user:user1:ids保存用户id,user:user1:detail保存用户的具体信息,两个key不可能同名。两个key其实有相同的地方,即user。能不能拿这一部分去计算hash呢?这就是 Hash Tag。容许用key的部分字符串来计算hash。atom

场景2

  1. 哈希标签是确保两个键都在同一个哈希槽里的一种方式,未来也许会使用到哈希标签,例如为了在集群稳定的状况下(没有在作碎片重组操做)容许某些多键操做。

Hash tag的使用介绍

为了实现哈希标签,哈希槽是用另外一种不一样的方式计算的。基原本说,若是一个键包含一个 “{…}” 这样的模式,只有 { 和 } 之间的字符串会被用来作哈希以获取哈希槽。可是因为可能出现多个 { 或 },计算的算法以下:代理

若是键包含一个 { 字符。
那么在 { 的右边就会有一个 }。
在 { 和 } 之间会有一个或多个字符,第一个 } 必定是出如今第一个 { 以后。
`

而后不是直接计算键的哈希,只有在第一个 { 和它右边第一个 } 之间的内容会被用来计算哈希值。当一个key包含 {} 的时候,就不对整个key作hash,而仅对 {} 包括的字符串作hash。code

hash值计算方式

假设hash算法为sha1。对user:{user1}:ids和user:{user1}:detail,其hash值都等同于sha1(user1)。ci

例子
  • 两个键 {user1000}.following 和 {user1000}.followers 会被哈希到同一个哈希槽里,由于只有 user1000 这个子串会被用来计算哈希值。
  • 对于 foo{}{bar} 这个键,整个键都会被用来计算哈希值,由于第一个出现的 { 和它右边第一个出现的 } 之间没有任何字符。
  • 对于 foozap 这个键,用来计算哈希值的是 {bar 这个子串,由于它是第一个 { 及其右边第一个 } 之间的内容。
  • 对于 foo{bar}{zap} 这个键,用来计算哈希值的是 bar 这个子串,由于算法会在第一次有效或无效(好比中间没有任何字节)地匹配到 { 和 } 的时候中止。

按照这个算法,若是一个键是以 {} 开头的话,那么就看成整个键会被用来计算哈希值。当使用二进制数据作为键名称的时候,这是很是有用的。element

Hash tag的注意事项

咱们在使用hashtag特性时,必定要注意,不能把key的离散性变得很是差。 没有利用hashtag特性以前,key是这样的:mall:sale:freq:ctrl:860000000000001,很明显这种key因为与用户相关,因此离散性很是好。 使用hashtag之后,key是这样的:mall:sale:freq:ctrl:{860000000000001},这种key仍是与用户相关,因此离散性依然很是好。字符串

糟糕的案例

千万不要这样来使用hashtag特性,例如:将key设置为:mall:{sale:freq:ctrl}:860000000000001。hash

这样的话,不管有多少个用户多少个key,其{}中的内容彻底同样都是sale:freq:ctrl,也就是说,全部的key都会落在同一个slot上,致使整个Redis集群出现严重的倾斜问题。it

Twemproxy的分片技术分析

twitter的 twemproxy 是一个Redis的代理服务程序,可以实现key的分片。分片能使key均匀地分布到集群的机器上去,能保证数据的一致性,有着众多的优势。 但从Redis单实例切换到twemproxy集群时,仍是有些须要注意的地方,不支持的方法:

KEYS,MIGRATE,SCAN等

支持但需特殊处理的方法:

MSET,SINTERSTORE,SUNIONSTORE,ZINTERSTORE,ZUNIONSTORE等

对于不支持的方法,在使用时须要寻找替代方案。本文主要解决一下需特殊处理的方法。 MSET 单实例上的MSET是一个原子性(atomic)操做,全部给定 key 都会在同一时间内被设置,某些给定 key 被更新而另外一些给定 key 没有改变的状况,不可能发生。 而集群上虽然也支持同时设置多个key,但再也不是原子性操做。会存在某些给定 key 被更新而另一些给定 key 没有改变的状况。其缘由是须要设置的多个key可能分配到不一样的机器上。

SINTERSTORE,SUNIONSTORE,ZINTERSTORE,ZUNIONSTORE

这四个命令属于同一类型。它们的共同之处是都须要对一组key进行运算或操做,但要求这些key都被分配到相同机器上。 这就是分片技术的矛盾之处: 即要求key尽量地分散到不一样机器,又要求某些相关联的key分配到相同机器。