天天看点

架构设计 | 分布式业务系统中,全局ID生成策略

本文源码:GitHub·点这里 || GitEE·点这里

在实际的开发中,几乎所有的业务场景产生的数据,都需要一个唯一ID作为核心标识,用来流程化管理。比如常见的:

订单:order-id,查订单详情,物流状态等;

支付:pay-id,支付状态,基于ID事务管理;

如何生成唯一标识,在普通场景下,一般的方法就可以解决,例如:

这个方法可以解决绝大部分唯一ID需求的场景业务,但是网上各种UUID重复场景的描述帖,说的好像该API不好用。

<code>絮叨一句</code>:说一个真实使用的业务场景,大概是半年近3000万的数据流水,用的就是UUID的API,暂时未捕捉到ID重复的问题,仅供参考。

Twitter公司开源的分布式ID生成算法策略,生成的ID遵循时间的顺序。

架构设计 | 分布式业务系统中,全局ID生成策略

1为位标识,始终为0,不可用;

41位时间截,存储时间截的差值(当前时间截-开始时间截);

10位的机器标识,10位的长度最多支持部署1024个节点;

12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒产生4096个ID序号;

SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高。

工具类中很多可以自定义的,比如起始时间,机器ID配置等。

还有一种常见的实现思路,基于数据库的自增主键ID,不过基于这个原理,却有各种不同的实现策略。

简单表结构:

架构设计 | 分布式业务系统中,全局ID生成策略

这种模式的原理比较单调,向临时表写入一条记录,借助MySQL生成的唯一主键ID,然后拿出来稍微处理一下,作为各种业务场景的唯一ID使用。

问题点:如果作为ID生成的临时表所在的MySQL服务宕掉,那可能会影响整个业务流程,造成雪崩效应。

单服务如果不能安稳的支撑业务需求,很自然集群模式就该上场了。提供多台MySQL服务[A,B,C],处理策略也不止一种:

库设置主键自增策略

例如A库[1,4,7],B库[2,5,8],C库[3,6,9],基于不同自增规则,生成统一的自增唯一标识。

生成ID做分库标识

这种先把ID生成,然后不同的数据库生成的ID给一个不同的标识,例如UIDA,UIDB,UIDC。

结果样例:

UID-A00001,UID-B00001,UID-C00001

UID-A00002,UID-B00002,UID-C00002

从数据获取的ID基本是一个自增的整数序列,可以提供一个格式美化工具方法。

基于不同的策略,把ID格式为统一的位数。

如果在高并发的业务场景下,实时基于MySQL去生成唯一ID容易产生性能瓶颈,当然其他方法也可能产生这个问题。可以在系统空闲时间批量生成一批,放入缓存中,在使用的时候直接从缓存层取出即可。

架构设计 | 分布式业务系统中,全局ID生成策略

推荐阅读:数据和架构管理

序号

标题

A01

数据源管理:主从库动态路由,AOP模式读写分离

A02

数据源管理:基于JDBC模式,适配和管理动态数据源

A03

数据源管理:动态权限校验,表结构和数据迁移流程

A04

数据源管理:关系型分库分表,列式库分布式计算

C01

架构基础:单服务.集群.分布式,基本区别和联系

继续阅读