-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
若机器时间回拨或者前置,如何保证序列号的唯一?有什么机制能保证本地时间变动不影响服务正常工作? #35
Comments
百度的id生成器是这样来处理的,每次的启动都在mysql里记录一个值,下次启动舍弃重新生成这个值,貌似支持百万级别以上的重复启动 |
@huaweihomelq 多谢回复。 是的,这个是机器工作节点ID的生成策略(用完即弃),但是我说的是另外一种情况:序列号生成服务正常运行,但是服务器的本地时间发生了变化,比如前移了几秒,那么服务好像就不能正常工作了,会发生序列号重复的情况。 因为服务强依赖本地时间。 这种场景有没有考虑,问题该如何解决? |
你所说的时钟回调,在应用介绍里貌似不是已经解决了吗?难道你现在使用的版本,已经存在并发生服务不可用的情况了?如果有的话,希望能了解下情况,我目前做的项目,都准备上线使用了,感觉有点恐怖 |
我现在没遇到这种情况,不过这种情况肯定是存在的。源代码中时钟不对直接抛出异常,并没有做其他额外的处理,比如如果时钟回调时间比较小,可以等待;或者增加冗余位进一处理等。 或者可以考虑:如果时钟回调则强制刷新到最新,这样应该就没这个问题了。这样就不会重复了。 源码如下: |
通过上面对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"这个时间产生的)。 |
第一种情况:实例关闭,时间回拨,重启实例。 |
No description provided.
The text was updated successfully, but these errors were encountered: