分布式状态服务架构
分布式状态服务架构设计
- 状态服务定义
- hash取模数据分片
- 分段hash
- 一致性hash
- redis hash 槽
- 一致性 hash 应用
当设计分布式状态服务,需要请求落在持有数据的正确的状态服务节点(粘性负载均衡),所以不能像无状态服务一样随意扩缩容,需要考虑到数据分片和负载均衡策略。
hash 取模数据分片
如图当状态服务节点数量为3个,使用hash取模算法hash(key) % 3
对客户端唯一key进行负载均衡,确保每次来自同一客户端的请求路由到同一个状态服务数据节点。
哈希取模分片的核心问题,对扩容不友好,扩容的时候数据迁移规模太大。
比如把节点从3个扩展到4个,分片算法调整为hash(key) % 4
,之前存储的大量数据需要重新计算存储节点并迁移,对所有数据重新进行分布。
若一定要采用哈希取模分片,建议采用多倍扩容的办法,如原先的3个节点扩容到6个节点,只需要迁移50%的数据,减少数据迁移量。
数据固定分片
如果分片键均衡增长,也可以采用固定数据分片策略。
如图,每个节点负责一个号段的请求,这里为1-300w, 300w-600w, 600w-1000w
,当号段超过1000w时增加新的节点,对现有节点无影响无需数据迁移。
客户端需要存储和及时更新号段与节点的映射关系。
Redis Cluster的分片策略
Redis 集群采用哈希槽 slots 对数据进行分片,固定16384个哈希槽,比如对于三个 Redis 节点,哈希槽的分配方式如下:
- 节点A拥有 0-5500 哈希槽
- 节点B拥有 5501-11000 哈希槽
- 节点C拥有剩余的 11001-16383 哈希槽
key 与 redis 节点之间的映射关系,使用CRC16哈希算法对key运算得到哈希值,对哈希槽数 16383 进行取模,得到key对应的哈希槽,通过哈希槽映射到对应的redis节点。
当集群扩容时,通过 reshard(重新分配),将现有节点的任意数量slot哈希槽及对应的数据迁移给新的节点。
一致性哈希
一致性哈希算法,可以保证当机器增加或者减少时,节点之间的数据迁移只限于两个节点之间,不会造成全局的网络问题。
如图,一致性哈希通过哈希环,将 A、B、C
三个节点通过哈希值映射到哈希环上对应位置,张三发出请求,通过hash(张三)得到哈希值,顺时针查找请求落在节点A上。
假如集群扩容节点D加入,哈希值为图中位置,此时只需将A节点中数据重新hash,将(B, D]
段迁移到D节点即可,其他节点不受影响。
虚拟节点
当集群节点数量较少时,一致性hash会导致负载不均衡,上图中明显节点A和B的负载更大。
通过引入虚拟节点,解决哈希环偏斜问题,让集群中的节点尽可能的多。