零一开源—技术|科技|资源分享 零一开源—技术|科技|资源分享

技术分享与兴趣交流

目录
雪花算法SnowFlake—利用hutool生成分布式订单唯一流水号和ID
/  

雪花算法SnowFlake—利用hutool生成分布式订单唯一流水号和ID

关于订单号的生成,有一些简单的方案

1,数据库自增长id

优势

无需编码

缺陷

大表不能做水平分表,否则插入删除时容易出现问题

高并发下插入数据需要加入失误机制

在业务操作父,子表(关联表)插入时,先要插入父表,再插入子表

2,时间戳+ 随机数

优势

编程简单

缺陷

随机数存在重复问题,即使在相同的时间戳下。每次插入数据库前需要校验下是否已经存在相同的数值。

3,时间戳+会员ID

优势

同一时间,一个用户不会存在2张订单

缺陷

会员ID也会透露出运营数据,鸡生蛋蛋生鸡的问题

4,GUID/UUID

优势

简单

劣势

用户不友好,索引关联效率较低

5 snowflake方案:

snowflake是Twitter开源的分布式ID 生成算法,结果是一个long型的ID

这种方案大致来说是一种以划分明明空间(UUID也算,由于比较常见,所以单独分析)来生成的ID 的一种算法,这种方案把64-bit分贝划分成多段,分开来提示机器,时间等;

其核心思想是: 使用41bit作为毫秒数,10bit作为机器的ID(5ge bit是数据中心,5个bit的机器ID),12bit 作为毫秒数内的流水号,最后一个符号位,永远是0.

比如在snowlake中的64-bit分别表示如下图(图片来自网络)表示

整个结构是64位,所以我们在Java中可以使用long来进行存储。该算法实现基本就是二进制操作,单机每秒内理论上最多可以生成1024*(2^12),也就是409.6万个ID(1024*4096=4194304)

优点

整体上按照时间自增排序,并且排序整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID做区分),并且效率高,轻测试,SnowFlaje每秒能产生26万ID左右。

缺点

强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务处于不可用状态,

针对此,美团做出了改进:https://github.com/Meituan-Dianping/Leaf

基于hutool工具类的SnowFlake算法代码

引入hutool依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-captcha</artifactId>
        <version>5.0.6</version>
</dependency>

ID 生成工具类

public class IdGenerator {
 
    private long workerId = 0;
 
    @PostConstruct
    void init() {
        try {
            workerId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
            log.info("当前机器 workerId: {}", workerId);
        } catch (Exception e) {
            log.warn("获取机器 ID 失败", e);
            workerId = NetUtil.getLocalhost().hashCode();
            log.info("当前机器 workerId: {}", workerId);
        }
    }
 
    /**
     * 获取一个批次号,形如 2019071015301361000101237
     * <p>
     * 数据库使用 char(25) 存储
     *
     * @param tenantId 租户ID,5 位
     * @param module   业务模块ID,2 位
     * @return 返回批次号
     */
    public synchronized String batchId(int tenantId, int module) {
        String prefix = DateTime.now().toString(DatePattern.PURE_DATETIME_MS_PATTERN);
        return prefix + tenantId + module + RandomUtil.randomNumbers(3);
    }
 
    @Deprecated
    public synchronized String getBatchId(int tenantId, int module) {
        return batchId(tenantId, module);
    }
 
    /**
     * 生成的是不带-的字符串,类似于:b17f24ff026d40949c85a24f4f375d42
     *
     * @return
     */
    public String simpleUUID() {
        return IdUtil.simpleUUID();
    }
 
    /**
     * 生成的UUID是带-的字符串,类似于:a5c8a5e8-df2b-4706-bea4-08d0939410e3
     *
     * @return
     */
    public String randomUUID() {
        return IdUtil.randomUUID();
    }
 
    private Snowflake snowflake = IdUtil.createSnowflake(workerId, 1);
 
    public synchronized long snowflakeId() {
        return snowflake.nextId();
    }
 
    public synchronized long snowflakeId(long workerId, long dataCenterId) {
        Snowflake snowflake = IdUtil.createSnowflake(workerId, dataCenterId);
        return snowflake.nextId();
    }
 
    /**
     * 生成类似:5b9e306a4df4f8c54a39fb0c
     * <p>
     * ObjectId 是 MongoDB 数据库的一种唯一 ID 生成策略,
     * 是 UUID version1 的变种,详细介绍可见:服务化框架-分布式 Unique ID 的生成方法一览。
     *
     * @return
     */
    public String objectId() {
        return ObjectId.next();
    }
 
}

}

Hutool官方给出的分布式IdUtil类的说明:
https://hutool.cn/docs/#/core/工具类/唯一ID工具-IdUtil?id=%e4%bb%8b%e7%bb%8d

参考自:https://www.jianshu.com/p/5c028b4b41f2?utm_campaign=haruki


标题:雪花算法SnowFlake—利用hutool生成分布式订单唯一流水号和ID
作者:hacken
地址:https://www.01open.com/articles/2022/01/14/1642168631488.html