如何设计一款“高可用高性能”的发号器?

简介: 在分布式场景中,很多地方需要生成全局唯一的id,如数据库分库分表后需要用唯一id代替单机版本的自增id。发号器的基本要求是全局唯一,无论如何都不能重复某些场景下还要求单调递增,如排序需求等。

背景


在分布式场景中,很多地方需要生成全局唯一的id,如数据库分库分表后需要用唯一id代替单机版本的自增id。发号器的基本要求是


  • 全局唯一,无论如何都不能重复


某些场景下还要求单调递增,如排序需求等。


网上有很多介绍发号器的文章,比如美团的《Leaf——美团点评分布式ID生成系统》,有赞的《如何做一个靠谱的发号器》等。本文聚焦高可用,高性能


  • 高可用:不会因为系统故障导致服务不可用或发号重复
  • 高性能:发号器通常是一个非常高并发的系统,性能足够的同时也可以水平扩容


在基本的要求下,常见的解决方案有哪些?他们是否是高可用高性能的呢?


snowflake方案


snowflake 采用41位时间戳加10位机器id加12位序列号的方式生成,序列号在单一进程内可使用AtomicLong来生成,10位机器号可支持1024台机器


640.jpg


该算法优点是:


  • 算法简单,易于实现,不依赖任何第三方系统,性能非常高;
  • 集群无状态,可随意扩缩容,可认为是高可用系统。


缺点是:


  • 高10位的时间戳和低位自增序列号可保证单调增,但机器号无法保证,如机器号为2在某一时刻先生成id,机器号为1在同一时刻后生成id,则不能保证单调性;
  • 依赖时间戳,如果时钟回拨,可能会生成重复的id。


综合来看,snowflake方案符合基本要求,性能非常高,但其存在时钟回拨问题,因而是高性能不是高可用的方案。


基于数据库方案


利用数据库的自增id特性实现,该方案优点:


  • 实现比较简单,只依赖数据库;
  • 没有时钟回拨问题;
  • 生成的id单调递增。


缺点:


  • 性能被数据库限制,数据库的单机写入性能有限,也无法扩缩容;
  • 数据库存在单点故障,如果是主从架构,取决于是异步复制半同步复制全同步复制配置,只有全同步复制才能保证可用性,其他配置无法保证主从数据的一致性,一旦主库发生故障,主库的变更还未应用到从库,则主从切换后可能会存在发号重复的问题。


同理,这里的数据库也可以替换为redis,利用redis的incr来实现,但redis只有异步复制,更加无法保证数据一致性。


综合来看,基于数据库的方案如果不开启全同步复制,就不是高可用方案,如果开启全同步复制,则性能一定会有问题(就算不开启全同步复制也会有性能问题)。


基于数据库的号段方案


本方案是对数据库方案的一种性能优化,每次从数据库取回的不是一个id,而是一个号段,在单独进程内通过锁保证每次发放一个唯一的id,甚至可以在系统快要发放完号码时异步地去获取下一个号段,该方案性能明显高于数据库方案,但也失去了id单调递增的特性,如果开启全同步复制,则可认为是一个高可用的方案,通过调大号段的长度,可以达到高性能的要求。


基于多主库的数据库方案


本方案也是对数据库号方案的一种优化,采用多台数据库,假设3台主库设置自增id起始分别为1,2,3,步长都设置为3,这样1号数据库获取的自增id为1,4,7...,2号数据库获取的自增id为2,5,8...,3号数据库获取的自增id为3,6,9...,他们永远不会重复。系统每次取号段时采取轮询策略,如果有一台数据库获取失败,则继续从下一个数据库获取。该方案解决了数据库的高可用问题,个别数据库宕机不影响系统正常运行。


高性能也是通过号段的方式来解决,如果运行过程中对数据库进行水平扩容则比较困难。


基于一致性协议的方案


上面数据库的高可用问题主要来源于主从数据不一致,如果使用一致性协议来保证数据的一致性,就可以解决高可用问题,目前最常使用的raft算法,可以保证数据复制到半数以上机器。在我们每获取一个号段后,已发出的号段都被持久化到半数以上机器,并且最终复制到所有机器,当master挂掉后raft重新选举。有赞的《如何做一个靠谱的发号器》就是采取这种办法,他们使用的组件是etcd。甚至可以基于开源的raft库来自己实现一个发号器,如果要自己来实现一个靠谱raft协议,还是比较困难的,开源的raft库可选用蚂蚁开源的SOFAJRaft


总结


  • 发号器的高性能主要依靠号段的方式来解决;
  • 发号器的高可用可以依靠数据库的高可用、多主库、一致性协议来实现。
相关文章
|
4月前
|
存储 运维 监控
如何设计高可用的分布式系统
【7月更文挑战第29天】设计高可用的分布式系统是一个复杂而细致的过程,需要从架构设计、冗余策略、故障转移与恢复、监控与告警等多个方面综合考虑。通过采用微服务架构、无状态服务、负载均衡、数据冗余、服务冗余、跨地域部署等策略,可以显著提高系统的可用性和可靠性。同时,建立完善的监控和告警体系,确保对系统的任何变化都能及时感知和处理。最终,通过不断的优化和改进,实现系统的高可用性目标。
|
4月前
|
负载均衡 安全 Cloud Native
云上负载均衡:构建高可用、高性能的网络应用架构
与云原生技术深度融合:随着云原生技术的普及和发展未来的云上负载均衡将更加紧密地与云原生技术相结合。例如与Kubernetes等容器编排平台集成实现自动化的服务发现和路由管理;与Serverless架构结合提供无缝的流量接入和请求处理能力。 安全性能提升:面对日益严峻的网络安全威胁云上负载均衡将更加注重安全性能的提升。通过引入加密传输、访问控制、DDoS防护等安全措施确保网络流量的安全性和隐私性;同时还将建立完善的安全监控和应急响应机制以应对各种安全事件和突发事件。 支持多协议和多场景:未来的云上负载均衡将支持更多种类的网络协议和应用场景以满足不同用户和业务的需求。例如支持HTTP/2、
240 0
|
5月前
|
消息中间件 缓存 Java
高性能架构设计
高性能架构设计
100 5
|
4月前
|
存储 缓存 监控
如何设计一个高可靠性的分布式缓存系统?
如何设计一个高可靠性的分布式缓存系统?
|
4月前
|
运维 负载均衡 监控
如何设计一个高可用的分布式系统?
如何设计一个高可用的分布式系统?
|
4月前
|
存储 负载均衡 Java
如何设计一个高可扩展的分布式架构?
如何设计一个高可扩展的分布式架构?
|
存储 缓存 算法
分布式数据库架构:高可用、高性能的数据存储
分布式数据库架构:高可用、高性能的数据存储
1006 0
|
缓存 监控 容灾
0-1设计高可用、高并发、高伸缩的分布式项目架构
0-1设计高可用、高并发、高伸缩的分布式项目架构
111 0
|
存储 缓存 NoSQL
互联网开发高可用高性能那点事
互联网开发高可用高性能那点事
|
消息中间件 监控 算法
高可用怎么设计呢
《高可用》系列
181 0
高可用怎么设计呢