背景
系统tps是3000,采用分布式部署,业务单号需要全局唯一,例如订单号。常见的分布式全局id的方案网上有很多种,大致有以下几种:
- UUID
- redis原子性自增
- zookeeper节点目录
- SnowFlake(雪花算法)
- 国内大厂基于雪花算法的算法,如美团的leaf
以上解决方案大致分为三类
- UUID
- 中间件(redis、zk)
- 类雪花算法
UUID
uuid实现较为简单,但是无规律,且长度太长,一方面无法与业务完美结合,另一方面数据库存储空间太大。
中间件
中间件的方式基本没有毛病,但是依赖第三方服务,一旦第三方服务不可用,基本凉凉。
类雪花算法
基本没有问题,可以封装成系统中的方法,直接调用,而且可以结合自身业务就行扩展,雪花算法有一个缺点:雪花算法的实现依赖于系统时间,如果回拨系统时间,全局id将不再唯一。
雪花算法简介
SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的。
这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号
雪花算法的核心有两点:
- 引入机器号
- 引入序列号
引入机器号的优点
引入机器号,系统中不同节点的生成的全局id可以区分出来了,不同节点间的并发对于系统全局id的影响没有了。
引入序列号
引用序列号的方法是如果当前秒与上一秒相同,序列号自增,否则序列号重置为零,引入序列号解决了同一个节点密集并发毫秒精度不足的局限性。
自我实现全局id
自我实现全局id同样是借鉴雪花算法的两个优秀思想:机器号和序列号
全局ID设计
这种设计同一机器一秒内可以生成10000个唯一的id,如果系统总共有100个节点,则一秒内可以生成100万个全局ID,后续业务增加,可以扩展序列号和机器号的位数即可。
代码实现
private static Long lasttime = -1L;
private static Integer sequence = 0