关于分布式id生成器生成单调递增id的思考

目录

 

如何保证获取到的id单调递增?

约束条件:

1)集群中一台机器为Master,仅Master提供id生成服务

2)当获取id的请求路由到Master机器时,直接返回响应(一轮RPC)

当获取id的请求路由到非Master机器时,转发至Master机器(两轮RPC)

 

方案评估

 

评估

性能

1)请求最终由Master机器进行响应。单机能支持的最大QPS即为集群最大QPS。

2)请求路由到非Master机器时,需两轮RPC,会增加耗时。

3)请求最终由Master机器进行响应,导致同机房优先路由策略不适用,某些情况下,请求耗时较长。

扩展性

集群总QPS无法随集群机器数量的增加而线性扩展。

可用性

1)当发生Master切换时,会损失一定可用性

2)某些情况下,请求耗时较长,会导致可用性降低。

 

评估详情

性能

(1)当获取id的请求最终由Master进行响应。单机能支持的最大QPS即为集群最大QPS。

(2)由于仅Master能够提供id生成服务,同机房优先等路由规则不再适用

情况1:当获取id的请求路由到Master

当获取id的请求路由到Master,直接返回响应,一轮RPC

case1:

client和Master同城市,比如都在Beijing

client(Beijing)----->server(Master,Beijing)

 

case2:

client和Master不同城市,比如一个Beijing,一个Shanghai

client(Beijing)--(25ms+)--->server(Master,Shanghai)

跨城市调用,获取id的耗时将达到25ms+。

 

情况2:当获取id的请求路由到非Master

当获取id的请求路由到非Master,转发至Master,两轮RPC

case 1:

当client和Master同城市,比如都在Beijing

client(Beijing)----->server(非Master,Beijing)----->server(Master,Beijing)

 

case2:

当client和Master不同城市,比如一个Beijing,一个Shanghai

client(Beijing)----->server(非Master,Beijing)--(25ms+)--->server(Master,Shanghai)

跨城市调用,获取id的耗时将达到25ms+。

 

极端情况:第一次获取id,Master从DB加载号段,跨城市

client(Beijing)----->server(非Master,Beijing)--(25ms+)--->server(Master,Shanghai)--(25ms+)--->DB(Beijing)

 

总结

当client和Master机器在不同城市时,获取id耗时较长。

 

扩展性

集群总QPS无法随集群机器数量的增加而线性扩展。

无论集群中机器有多少台,集群QPS为单机最大QPS

 

可用性

1)由于同机房优先等路由规则不再适用,耗时明显增加,超时概率大大提高。

2)切换Master期间,id生成服务会短暂不可用,且不可避免

 

可导致Master切换的情况

1)禁用Master机器

2)重启Master

3)机器宕机

 

Master切换

1)探测到需要切换Master

当禁用Master机器的时候,怎么探测到需要切换Master?

2)选举新的Master

3)新Master提供服务

新Master从DB获取新号段,对于路由到非Master的请求将转发到新Master

 

如何处理Master切换时的id分发问题,保证在Master切换时的可用性?

Master切换期间,id生成服务短暂不可用,且不可避免,只能够尽量做到client端无明显感知

此处无明显感知是指

1)Master切换时,client端获取id的耗时无明显增加,否则导致超时增多

2)Master切换时,获取id服务短暂不可用,应保证获取到异常的id的数量无明显增加

 

附录

微信序列号生成器如何实现唯一、递增的

https://www.infoq.cn/article/wechat-serial-number-generator-architecture/

实现唯一、递增的约束条件:有且仅有一台server提供服务

 

 

 

图 5. 两台 AllocSvr 服务同个 uid 造成 sequence 回退。Client 读取到的 sequence 序列为 101、201、102

解决方法:仅有一台Master提供服务,Master不可用时,切换新Master

总结就是:

1)单台Master提供id生成服务。

2)引入仲裁服务,仲裁服务探测Master可用性,当Master不可用时,指定新的Master

3)其他机器定时检测配置,判断新Master是不是自己,是的话,作为新Master提供服务

 

为了避免Master切换过程中,旧的Master产生脏数据,引入了租约机制。

但是租约机制会导致id生成服务一段时间内不可用,此时,微信通过重试解决这段时间的不可用问题。

图 6. 号段迁移示意。通过更新加载配置把 0~2 号段从 AllocSvrA 迁移到 AllocSvrB

同时,为了避免失联 AllocSvr 提供错误的服务,返回脏数据,AllocSvr 需要跟 StoreSvr 保持租约。这个租约机制由以下两个条件组成:

  1. 租约失效:AllocSvr N 秒内无法从 StoreSvr 读取加载配置时,AllocSvr 停止服务

  2. 租约生效:AllocSvr 读取到新的加载配置后,立即卸载需要卸载的号段,需要加载的新号段等待 N 秒后提供服务

 

图 7. 租约机制。AllocSvrB 严格保证在 AllocSvrA 停止服务后提供服务

这两个条件保证了切换时,新 AllocSvr 肯定在旧 AllocSvr 下线后才开始提供服务。但这种租约机制也会造成切换的号段存在小段时间的不可服务,不过由于微信后台逻辑层存在重试机制及异步重试队列,小段时间的不可服务是用户无感知的,而且出现租约失效、切换是小概率事件,整体上是可以接受的。

(由于微信序列号生成器的使用场景的特殊性,对于短时间内id生成服务的不可用是可以容忍的)

 

posted @ 2020-03-27 00:01  Ye_yang  阅读(1472)  评论(0编辑  收藏  举报