分布式系统下的唯一序列
分布式系统中,全网唯一序列号
作用:保证在分布式系统下,不同业务模块的业务操作独立性和唯一性,并且可适用于高并发场景。
常见业务场景:全局订单Id,唯一标识的支付编号等。
唯一序列的特征:
全局唯一:确保生成的序列全局唯一,不可重复;
有序递增:确保生成的序列对某个用户或业务是按序递增,如事务版本号、IM增量消息、排序等特殊需求;
高可用性:确保生成的序列功能的高可用,能够承接较大峰值,能够保证序列生成的有效性(不重复且有序);
时间标记:序列中有时间片段组成,可清晰识别出操作的时间。
分布式系统下的唯一序列的实现方案
1、UUID
UUID(Universally Unique Identifier)的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的36个字符,示例:550e8400-e29b-41d4-a716-446655440000
生成方式:
(1)UUID工具包
Maven依赖:
<dependency> <groupId>com.fasterxml.uuid</groupId> <artifactId>java-uuid-generator</artifactId> <version>4.0</version> </dependency>
使用示例:
//UUID Version 1:基于时间的UUID(全球唯一) UUID uuid1 = Generators.timeBasedGenerator().generate(); //UUID Version 3:基于名字的UUID(相关名字重复) UUID uuid3 = Generators.nameBasedGenerator().generate("sai"); //UUID Version 4:随机UUID(java自带版本,极小概率重复) UUID uuid4 = Generators.randomBasedGenerator().generate();
(2)Java的UUID工具类
import java.util.UUID; public class JavaUUIDTest { public static void main(String[] args) { //未加工的UUID String preUuid = UUID.randomUUID().toString(); System.out.println(preUuid); //第一种方法生成UUID,去掉“-”符号 System.out.println(UUID.randomUUID().toString().replace("-", "")); //未加工的UUID String preUuid2 = UUID.randomUUID().toString(); System.out.println(preUuid2); //第二种生成UUID的方法,去掉“-”符号 String changUuid = preUuid2.substring(0,8)+preUuid2.substring(9,13)+preUuid2.substring(14,18)+preUuid2.substring(19,23)+preUuid2.substring(24); System.out.println(changUuid); } }
优点:本地生成,无网络消耗,性能非常高。
缺点:太长不易于存储;无时间标识;数据可读性差;不能有序递增;基于MAC地址生成,可能造成MAC地址泄露。
2、数据库生成
数据库设置主键自增:
MySQL:auto_increment
Oracle:自增序列+触发器
优点:操作简单,明显可控,有序自增。
缺点:依赖数据库,不适于高并发。
3、系统时间戳
生成方式:当前系统时间(精确到毫秒数或时间戳)+业务属性+用户属性+随机数+...等参数组合形式。
例如: 滴滴:时间+起点编号+车牌号 淘宝订单:时间戳+用户ID
可保证唯一性,不能保证有序性。
4、Redis生成唯一序列
使用Redis的String类型,及原子操作 incr/decr key 来实现,保证生成系列唯一有序。
incr/decr key // 自增减 1 incrby/decrby key increment // 自增减指定数值
incrbyfloat/decrbyfloat key increment // 自增减浮点数
优点:有序自增;不依赖于数据库,灵活方便,性能优于数据库。
缺点:增加Redis维护成本(编码、配置等),高并发时需设置Redis集群。
另外,利用zookeeper的znode数据版本来生成序列号 和 MongoDB的ObjectId 性能不如Redis。
5、snowflake(雪花算法)
生成方式:通过把 64bit 分别划分成 41bit 时间戳、10bit 工作机器id、12bit 序列号 的不同的命名空间生成序列id。
-
41位的时间序列,精确到毫秒,可以使用69年
-
10位的机器标识,最多支持部署1024个节点
-
12位的序列号,支持每个节点每毫秒产生4096个ID序号,最高位是符号位始终为0。
优点:
- 毫秒数在高位,自增序列在低位,整个ID趋势递增。
- 不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能非常高。
- 可根据自身业务特性分配bit位,非常灵活。
缺点:强依赖机器时钟,若机器上时钟回拨,会导致发号重复或服务不可用。
6、UidGenerator
百度开源的一款分布式高性能的唯一ID生成器,Java实现, 基于Snowflake算法的唯一ID生成器。
GitHub:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md
7、Leaf
美团开源的分布式ID生成器,能保证全局唯一性、趋势递增、单调递增、信息安全,同时也需要依赖关系数据库、Zookeeper等中间件。
美团技术社区详情说明:https://tech.meituan.com/2017/04/21/mt-leaf.html
本文作者:青志暖阳、惜殇
本文链接:https://www.cnblogs.com/qzny/p/16376800.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步