分布式架构系统生成全局唯一序列号的一个思路

分布式架构系统生成全局唯一序列号的一个思路

作者:佚名 2017-11-22 09:46:53

存储

存储软件

分布式 分布式架构下,唯一序列号生成是我们在设计一个系统,尤其是数据库使用分库分表的时候常常会遇见的问题。当分成若干个sharding表后,如何能够快速拿到一个唯一序列号,是经常遇到的问题。

 一、相关背景

分布式架构下,唯一序列号生成是我们在设计一个系统,尤其是数据库使用分库分表的时候常常会遇见的问题。当分成若干个sharding表后,如何能够快速拿到一个唯一序列号,是经常遇到的问题。

在携程账号数据库迁移MySql过程中,我们对用户ID的生成方案进行了新的设计,要求能够支撑携程现有的新用户注册体量。

本文通过携程用户ID生成器的实现,希望能够对大家设计分库分表的唯一id有一些新的思路。

[[210819]]

二、特性需求

  1. 全局唯一
  2. 支持高并发
  3. 能够体现一定属性
  4. 高可靠,容错单点故障
  5. 高性能

三、业内方案

生成ID的方法有很多,来适应不同的场景、需求以及性能要求。

常见方式有:

1、利用数据库递增,全数据库唯一。

优点:明显,可控。

缺点:单库单表,数据库压力大。

2、UUID, 生成的是length=32的16进制格式的字符串,如果回退为byte数组共16个byte元素,即UUID是一个128bit长的数字,一般用16进制表示。

优点:对数据库压力减轻了。

缺点:但是排序怎么办?

此外还有UUID的变种,增加一个时间拼接,但是会造成id非常长。

3、twitter在把存储系统从MySQL迁移到Cassandra的过程中由于Cassandra没有顺序ID生成机制,于是自己开发了一套全局唯一ID生成服务:Snowflake。

  1. 41位的时间序列(精确到毫秒,41位的长度可以使用69年)
  2. 10位的机器标识(10位的长度最多支持部署1024个节点)
  3. 12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号) ***位是符号位,始终为0。

优点:高性能,低延迟;独立的应用;按时间有序。

缺点:需要独立的开发和部署。

4、Redis生成ID

当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作INCR和INCRBY来实现。

可以使用Redis集群来获取更高的吞吐量。假如一个集群中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然后步长都是5。各个Redis生成的ID为:

A:1,6,11,16,21

B:2,7,12,17,22

C:3,8,13,18,23

D:4,9,14,19,24

E:5,10,15,20,25

比较适合使用Redis来生成每天从0开始的流水号。比如订单号=日期+当日自增长号。可以每天在Redis中生成一个Key,使用INCR进行累加。

优点:

不依赖于数据库,灵活方便,且性能优于数据库。

数字ID天然排序,对分页或者需要排序的结果很有帮助。

使用Redis集群也可以防止单点故障的问题。

缺点:

如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。

需要编码和配置的工作量比较大,多环境运维很麻烦,

在开始时,程序实例负载到哪个redis实例一旦确定好,未来很难做修改。

5.   Flicker的解决方案

因为MySQL本身支持auto_increment操作,很自然地,我们会想到借助这个特性来实现这个功能。

Flicker在解决全局ID生成方案里就采用了MySQL自增长ID的机制(auto_increment + replace into + MyISAM)。

6.还有其他一些方案,比如京东淘宝等电商的订单号生成。因为订单号和用户id在业务上的区别,订单号尽可能要多些冗余的业务信息,比如:

滴滴:时间+起点编号+车牌号

淘宝订单:时间戳+用户ID

其他电商:时间戳+下单渠道+用户ID,有的会加上订单***个商品的ID。

而用户ID,则要求含义简单明了,包含注册渠道即可,尽量短。

四、最终方案

最终我们选择了以flicker方案为基础进行优化改进。具体实现是,单表递增,内存缓存号段的方式。

首先建立一张表,像这样:

SEQUENCE_GENERATOR_TABLE

id   stub

1    192.168.1.1

其中id是自增的,stub是服务器ip

因为新数据库采用mysql,所以使用mysql的独有语法 replace to来更新记录来获得唯一id,例如这样:

  1. REPLACE INTO SEQUENCE_GENERATOR_TABLE (stub) VALUES (“192.168.1.1”); 

再用SELECT id FROM SEQUENCE_GENERATOR_TABLEWHERE stub = “192.168.1.1”;   把它拿回来。

到上面为止,我们只是在单台数据库上生成ID,从高可用角度考虑,接下来就要解决单点故障问题。

这也就是为什么要有这个机器ip字段呢?就是为了防止多服务器同时更新数据,取回的id混淆的问题。

所以,当多个服务器的时候,这个表是这样的:

id   stub

5    192.168.1.1

2    192.168.1.2

3    192.168.1.3

4    192.168.1.4

每台服务器只更新自己的那条记录,保证了单线程操作单行记录。

这时候每个机器拿到的分别是5,2,3,4这4个id。

至此,我们似乎解决这个服务器隔离,原子性获得id的问题,也和flicker方案基本一致。

但是追根溯源,在原理上,方案还是依靠数据库的特性,每次生成id都要请求db,开销很大。我们对此又进行优化,把这个id作为一个号段,而并不是要发出去的序列号,并且这个号段是可以配置长度的,可以1000也可以10000,也就是对拿回来的这个id放大多少倍的问题。

OK,我们从DB一次查询操作的开销,拿回来了1000个用户id到内存中了。

现在的问题就是要解决同一台服务器在高并发场景,让大家顺序拿号,别拿重复,也别漏拿。

这个问题简单来说,就是个保持这个号段对象隔离性的问题。

AtomicLong是个靠谱的办法。

当***次拿回号段id后,扩大1000倍,然后赋值给这个变量atomic,这就是这个号段的***个号码。

  1. atomic.set(n * 1000); 

并且内存里保存一下***id,也就是这个号段的***一个号码

  1. currentMaxId = (n + 1) * 1000; 

一个号段就形成了。

此时每次有请求来取号时候,判断一下有没有到***一个号码,没有到,就拿个号,走人。

  1. Long uid = atomic.incrementAndGet(); 

如果到达了***一个号码,那么阻塞住其他请求线程,最早的那个线程去db取个号段,再更新一下号段的两个值,就可以了。

这个方案,核心代码逻辑不到20行,解决了分布式系统序列号生成的问题。

这里有个小问题,就是在服务器重启后,因为号码缓存在内存,会浪费掉一部分用户ID没有发出去,所以在可能频繁发布的应用中,尽量减小号段放大的步长n,能够减少浪费。

经过实践,性能的提升远远重要于浪费一部分id。

如果再追求***,可以监听spring或者servlet上下文的销毁事件,把当前即将发出去的用户ID保存起来,下次启动时候再捞回内存即可。

五、上线效果

运行5个多月,十分稳定。

SOA服务平均响应时间 0.59毫秒;

客户端调用平均响应时间2.52毫秒;

附流程图:

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/261491.html<

(0)
管理的头像管理
上一篇2025-05-03 16:08
下一篇 2025-05-03 16:10

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注