一般方法

1.直接抛异常

2.延迟等待到最新时间(需要回拨时间比较短)

3.采用历史最大时间

package com.zjq.javabasic.algorithm;/*** @description: 雪花算法-时间回拨问题* @create: 2022-01-20 16:55**/
public class SnowflakeTest {/*** 最大容忍时间, 单位毫秒, 即如果时钟只是回拨了该变量指定的时间, 那么等待相应的时间即可;* 考虑到sequence服务的高性能, 这个值不易过大*/private static final long MAX_BACKWARD_MS = 5;/*** 开始时间戳,单位毫秒;这里是2021-06-01*/private static final long TW_EPOCH = 1622476800000L;/*** 机器 ID 所占的位数*/private static final long WORKER_ID_BITS = 5L;/*** 数据标识 ID 所占的位数*/private static final long DATA_CENTER_ID_BITS = 5L;/*** 支持的最大机器ID,最大为31* <p>* PS. Twitter的源码是 -1L ^ (-1L << workerIdBits);这里最后和-1进行异或运算,由于-1的二进制补码的特殊性,就相当于进行取反。*/private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);/*** 支持的最大机房ID,最大为31*/private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);/*** 序列在 ID 中占的位数*/private static final long SEQUENCE_BITS = 12L;/*** 机器 ID 向左移12位*/private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;/*** 机房 ID 向左移17位*/private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;/*** 时间截向左移22位*/private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;/*** 生成序列的掩码最大值,最大为4095*/private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);/*** 工作机器 ID(0~31)*/private final long workerId;/*** 机房 ID(0~31)*/private final long dataCenterId;/*** 毫秒内序列(0~4095)*/private long sequence = 0L;/*** 上次生成 ID 的时间戳*/private long lastTimestamp = -1L;/*** 创建 ID 生成器的方式一: 使用工作机器的序号(也就是将机房的去掉给机器ID使用),范围是 [0, 1023],优点是方便给机器编号** @param workerId 工作机器 ID*/public SnowflakeTest(long workerId) {// 计算最大值long maxMachineId = (MAX_DATA_CENTER_ID + 1) * (MAX_WORKER_ID + 1) - 1;if (workerId < 0 || workerId > maxMachineId) {throw new IllegalArgumentException(String.format("Worker ID can't be greater than %d or less than 0", maxMachineId));}// 取高位部分作为机房ID部分this.dataCenterId = (workerId >> WORKER_ID_BITS) & MAX_DATA_CENTER_ID;// 取低位部分作为机器ID部分this.workerId = workerId & MAX_WORKER_ID;}/*** 创建 ID 生成器的方式二: 使用工作机器 ID 和机房 ID,优点是方便分机房管理** @param dataCenterId 机房 ID (0~31)* @param workerId     工作机器 ID (0~31)*/public SnowflakeTest(long dataCenterId, long workerId) {if (workerId > MAX_WORKER_ID || workerId < 0) {throw new IllegalArgumentException(String.format("Worker ID can't be greater than %d or less than 0", MAX_WORKER_ID));}if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {throw new IllegalArgumentException(String.format("DataCenter ID can't be greater than %d or less than 0", MAX_DATA_CENTER_ID));}this.workerId = workerId;this.dataCenterId = dataCenterId;}/*** 获得下一个 ID(该方法是线程安全的)** @return 返回一个长度位15的 long类型的数字*/public synchronized long nextId() {long timestamp = timeGen();// 如果当前时间小于上一次 ID 生成的时间戳,说明发生时钟回拨,为保证ID不重复抛出异常。if (timestamp < lastTimestamp) {//如果小于容忍时间,直接设置历史最大时间long backTime = lastTimestamp - timestamp;if (backTime < MAX_BACKWARD_MS) {timestamp = lastTimestamp;} else {//抛异常throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}}if (lastTimestamp == timestamp) {// 同一时间生成的,则序号+1sequence = (sequence + 1) & SEQUENCE_MASK;// 毫秒内序列溢出:超过最大值if (sequence == 0) {// 阻塞到下一个毫秒,获得新的时间戳timestamp = tilNextMillis(lastTimestamp);}} else {// 时间戳改变,毫秒内序列重置sequence = 0L;}// 上次生成 ID 的时间戳lastTimestamp = timestamp;// 移位并通过或运算拼到一起return ((timestamp - TW_EPOCH) << TIMESTAMP_LEFT_SHIFT)| (dataCenterId << DATA_CENTER_ID_SHIFT)| (workerId << WORKER_ID_SHIFT)| sequence;}private long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}public static void main(String[] args) {SnowflakeTest snowflakeTest = new SnowflakeTest(0, 0);System.out.println(snowflakeTest.nextId());}
}

雪花算法生成分布式ID的时间回拨问题处理相关推荐

  1. 基于雪花算法生成用户id

    8.1 为啥这样做 1.全局唯一性,不会出现重复的id.如果通过id自增来保证id不重复,则该表 无法分表操作例如 服务器A的数据库的user表 数据如下1 小明 男2 小红 女2 张三 男此时 进行 ...

  2. DefaultIdentifierGenerator 雪花算法 生成 重复 id 解决办法

    DefaultIdentifierGenerator 雪花算法 生成 重复 id 前言 问题发生 排查原因 问题解决 前言 利用 mybatisplus 的 DefaultIdentifierGene ...

  3. 雪花算法snowflake分布式id生成原理详解,以及对解决时钟回拨问题几种方案讨论

    文章目录 一.前言 二.雪花算法snowflake 1.基本定义 2.snowflake的优缺点 三.Java代码实现snowflake 1.组装生成id 2.计算最大值的几种方式 3.反解析ID 4 ...

  4. 分布式下使用雪花算法生成全局ID及解决时钟回拨问题

    简介 雪花算法是 64 位 的二进制,一共包含了四部分: 1位是符号位,也就是最高位,始终是0,没有任何意义,因为要是唯一计算机二进制补码中就是负数,0才是正数 41位是时间戳,具体到毫秒,41位的二 ...

  5. 雪花算法【分布式ID问题】【刘新宇】

    分布式ID 1 方案选择 UUID UUID是通用唯一识别码(Universally Unique Identifier)的缩写,开放软件基金会(OSF)规范定义了包括网卡MAC地址.时间戳.名字空间 ...

  6. 推特雪花算法,分布式id生成器

    推特雪花算法 分布式id生成器 package util;import java.lang.management.ManagementFactory; import java.net.InetAddr ...

  7. python版雪花算法生成唯一ID

    一.雪花算法图解 理论一大堆,总结如下图: 下方为源码,返回的结果为19位,为10进制表示,使用二进制表示就是64位,所以不必有所疑惑. 二.源码 1.异常捕获块 文件名:exceptions.py ...

  8. 雪花算法:分布式唯一 ID 生成利器

    无论是在分布式系统中的 ID 生成,还是在业务系统中请求流水号这一类唯一编号的生成,都是软件开发人员经常会面临的一场景.而雪花算法便是这些场景的一个解决方案. 以分布式 ID 为例,它的生成往往会在唯 ...

  9. 雪花算法:分布式唯一ID生成利器

    前言 无论是在分布式系统中的ID生成,还是在业务系统中请求流水号这一类唯一编号的生成,都是软件开发人员经常会面临的一场景.而雪花算法便是这些场景的一个解决方案. 以分布式ID为例,它的生成往往会在唯一 ...

最新文章

  1. 2020 北京智源大会“云上”开幕, 中外顶尖学者畅想AI的下一个十年
  2. python导入csv文件-Python读写文件(csv、txt、excel)
  3. Java工具类--雪花算法生成全局唯一ID
  4. “约见”面试官系列之常见面试题第七篇说说Vue的生命周期(建议收藏)
  5. netpref 使用_使用PerfView监测.NET程序性能(转发)
  6. idea没有代码自动提示功能和包自动引入不了问题
  7. 12.2 新特性:锁信息获取之在线删除索引
  8. 双显卡只用独显好吗_双动力洗衣机好吗
  9. android读写相册权限,androidQ 关于存储权限相册图片
  10. 计算机应用基础任务化教程试题及答案,计算机应用基础任务化教程windows7office2010试卷(带操作题)及答案.doc...
  11. 网页输入数据到mysql_为什么用PHP编写的网页中,输入的数据不能插入到Mysql数据库中?...
  12. 【Java】Java_03第一个Java程序
  13. Numpy的各种下标操作
  14. STM8入门以及程序编译、烧录、IAR使用方法(扫盲篇)
  15. 【ubuntu查看显卡、配置显卡、cuda、cudnn】
  16. 艺赛旗(RPA)相对路径、绝对路径、执行空间、代码空间,傻傻分不清?
  17. 怎么样才能学好java_论新手该如何学习java?
  18. 不到七千入手的高性能笔记本,游匣G15实测
  19. A/B compartment:染色质区室简介
  20. 给自己定个小目标:每天写点东西

热门文章

  1. 运用免费OA让你有意想不到的效果
  2. CSDN高校巡讲石大站—青岛易软天创CEO王春生与我们分享“学习 工作 创业”
  3. java根据模板生成pdf文件并导出(iText)
  4. 单元测试 php,PHP单元测试PHPUnit简单用法示例
  5. 基于Java毕业设计在线药物配送系统源码+系统+mysql+lw文档+部署软件
  6. 小扰动线性化思想在机器学习中的跨界应用
  7. 《C++入门经典(第5版•修订版)》——2.7 作业
  8. Request URI does not contain a valid hostname: service-eureka-order/order/1 解决方法
  9. 最恐怖的 Cosplay。
  10. 融城杯 | 神州信息:金融科技助力乡村振兴