Code Monkey home page Code Monkey logo

Comments (6)

Timyooo avatar Timyooo commented on June 27, 2024 2

第一种情况:实例关闭,时间回拨,重启实例。
这种情况下,实例每次重启都分配一个新的workId,保证了重启后生成的id与之前产生的id不会重。
第二种情况:实例一直运行,时间回拨。
DefautlUidGenerator使用了System.currentTimeMillis()获取时间与上一次时间比较,可能会有currentTime<lastTime情况发生,抛错错误。
而CachedUidGenerator使用 AtomicLong的incrementAndGet()来获取下一次时间,脱离了时间,所以可以正常使用。

from uid-generator.

huaweihomelq avatar huaweihomelq commented on June 27, 2024 1

通过上面对UidGenerator的分析可知,CachedUidGenerator方式主要通过采取如下一些措施和方案规避了时钟回拨问题和增强唯一性:

自增列:UidGenerator的workerId在实例每次重启时初始化,且就是数据库的自增ID,从而完美的实现每个实例获取到的workerId不会有任何冲突。

RingBuffer:UidGenerator不再在每次取ID时都实时计算分布式ID,而是利用RingBuffer数据结构预先生成若干个分布式ID并保存。

时间递增:传统的雪花算法实现都是通过System.currentTimeMillis()来获取时间并与上一次时间进行比较,这样的实现严重依赖服务器的时间。而UidGenerator的时间类型是AtomicLong,且通过incrementAndGet()方法获取下一次的时间,从而脱离了对服务器时间的依赖,也就不会有时钟回拨的问题(这种做法也有一个小问题,即分布式ID中的时间信息可能并不是这个ID真正产生的时间点,例如:获取的某分布式ID的值为3200169789968523265,它的反解析结果为{"timestamp":"2019-05-02 23:26:39","workerId":"21","sequence":"1"},但是这个ID可能并不是在"2019-05-02 23:26:39"这个时间产生的)。

参考:https://www.jianshu.com/p/5509cc1b9a94

from uid-generator.

huaweihomelq avatar huaweihomelq commented on June 27, 2024

百度的id生成器是这样来处理的,每次的启动都在mysql里记录一个值,下次启动舍弃重新生成这个值,貌似支持百万级别以上的重复启动

from uid-generator.

jieniyimiao avatar jieniyimiao commented on June 27, 2024

@huaweihomelq 多谢回复。 是的,这个是机器工作节点ID的生成策略(用完即弃),但是我说的是另外一种情况:序列号生成服务正常运行,但是服务器的本地时间发生了变化,比如前移了几秒,那么服务好像就不能正常工作了,会发生序列号重复的情况。 因为服务强依赖本地时间。 这种场景有没有考虑,问题该如何解决?

from uid-generator.

huaweihomelq avatar huaweihomelq commented on June 27, 2024

你所说的时钟回调,在应用介绍里貌似不是已经解决了吗?难道你现在使用的版本,已经存在并发生服务不可用的情况了?如果有的话,希望能了解下情况,我目前做的项目,都准备上线使用了,感觉有点恐怖

from uid-generator.

jieniyimiao avatar jieniyimiao commented on June 27, 2024

我现在没遇到这种情况,不过这种情况肯定是存在的。源代码中时钟不对直接抛出异常,并没有做其他额外的处理,比如如果时钟回调时间比较小,可以等待;或者增加冗余位进一处理等。
我目前还处于开发预研阶段、还没上线,因为只要使用snowflake机制必然会出现这个问题,所以我这边有些担忧。
我们项目中准备把mybatis替换为JPA,Spirng 替换为Spring boot , 然后在做一些适应性的改造。

或者可以考虑:如果时钟回调则强制刷新到最新,这样应该就没这个问题了。这样就不会重复了。

源码如下:
// Clock moved backwards, refuse to generate uid
if (currentSecond < lastSecond) {
long refusedSeconds = lastSecond - currentSecond;
throw new UidGenerateException("Clock moved backwards. Refusing for %d seconds", refusedSeconds);
}

from uid-generator.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.