基于雪花算法实现的数据库唯一ID工具类

package com.ideatech.ams.ucam.utils;

/**
 * Created with IntelliJ IDEA.
 * 用于生成唯一的数据库ID的工具类,基于雪花算法实现。
 * <p>
 * 雪花算法的特点:
 * - 时间有序:生成的ID随时间递增,保证了ID的时序性。
 * - 唯一性:在同一毫秒内生成的ID不会重复。
 * - 分布式友好:适用于分布式系统,避免ID冲突。
 * <p>
 * 使用方式:
 * 调用 generateUniqueId() 方法可以生成唯一的ID。
 * <p>
 * 注意事项:
 * - 需要确保系统时钟不回退,以避免生成的ID不连续。
 * - 在高并发情况下,需要测试生成的ID是否唯一。
 *
 * @author Gotham
 * @date 2023/9/23 Time: 15:41
 * Email: Gotham
 */
public class IdInitUtil {
    private static final long EPOCH = 1632360000000L; // 设置一个起始时间戳(2021-09-24)
    private static final long SEQUENCE_BITS = 12;
    private static final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1;
    private static final long SEQUENCE_SHIFT = 0;
    private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS;
    private static final long MAX_SEQUENCE_NUMBER = 999L; // 每毫秒最多生成999个ID

    private static long lastTimestamp = -1L;
    private static long sequence = 0L;

    /**
     * 生成数据库唯一ID方法
     *
     * @return 唯一ID
     * @throws RuntimeException 如果时钟回退或每毫秒生成的ID数量超过最大限制,将抛出异常
     */
    public synchronized static long generateUniqueId() {
        long currentTimestamp = System.currentTimeMillis();

        if (currentTimestamp < lastTimestamp) {
            throw new RuntimeException("时钟回退异常");
        }

        if (currentTimestamp == lastTimestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;

            if (sequence == 0) {
                // 当前毫秒内生成的ID超过最大限制
                currentTimestamp = waitUntilNextMillis(currentTimestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = currentTimestamp;

        long id = ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) | (sequence << SEQUENCE_SHIFT);

        if (sequence > MAX_SEQUENCE_NUMBER) {
            throw new RuntimeException("每毫秒生成的ID数量超过最大限制");
        }

        return id;
    }

    /**
     * 生成数据库唯一ID方法
     *
     * @return 唯一ID
     * @throws RuntimeException 如果时钟回退或每毫秒生成的ID数量超过最大限制,将抛出异常
     */
    public synchronized static long generateNumber() {
        long currentTimestamp = System.currentTimeMillis();

        if (currentTimestamp < lastTimestamp) {
            throw new RuntimeException("时钟回退异常");
        }

        if (currentTimestamp == lastTimestamp) {
            sequence = (sequence + 1) & MAX_SEQUENCE;

            if (sequence == 0) {
                // 当前毫秒内生成的ID超过最大限制
                currentTimestamp = waitUntilNextMillis(currentTimestamp);
            }
        } else {
            sequence = 0L;
        }

        lastTimestamp = currentTimestamp;

        long id = ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) | (sequence << SEQUENCE_SHIFT);

        if (sequence > MAX_SEQUENCE_NUMBER) {
            throw new RuntimeException("每毫秒生成的ID数量超过最大限制");
        }

        return id;
    }

    /**
     * 在同一毫秒内等待,直到下一个毫秒
     *
     * @param currentTimestamp 当前时间戳
     * @return 下一个毫秒的时间戳
     */
    private static long waitUntilNextMillis(long currentTimestamp) {
        while (currentTimestamp <= lastTimestamp) {
            currentTimestamp = System.currentTimeMillis();
        }
        return currentTimestamp;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值