Leaf
Leaf copied to clipboard
关于Leaf-snowflake解决时钟回拨的本质
不知道是不是理解错误,本质就是用zookeeper判断是否发生时钟回拨,发生就报警? 本地保存上次时间戳不就可以判断是否回拨吗?
zookeeper除了起保存上次时间戳的作用,还起给每个ip:port分配一个固定的workId的作用(通过在zookeeper特定路径下创建永久有序节点,序号作为workId),如果不用zookeeper,那么使用新的机器或者新的端口部署leaf服务会没法获得唯一的workId。所以不知道考虑到一些小公司,他们在使用leaf时,需要单独维护一个zookeeper集群,是否代价太大,能否增加以下两种workId分配方式: 1.使用数据库来作为注册中心, 使用数据库替代替代zookeeper,因为一般的后端项目都会使用到数据库的概率,而不一定会有专门维护的zookeeper集群。 2.在项目中显式分配workID 针对一些小公司,他们可能一般部署leaf服务的ip和port不会变化。在项目中的配置文件显式得配置某某ip:某某port对应哪个workId,每次部署新机器,新port的时候在项目中添加这个配置,然后时间戳也每次同步到机器上。
@Yaccc 你好,这两种workId分配方式我已经开发完成,稍后会push到我fork的项目中https://github.com/NotFound9/Leaf 不知道Leaf项目需不需要这两种模式,如果Leaf项目需要这两种模式,我也希望可以给Leaf项目提PR,谢谢了
@hellolvs 你好,原有的模式在连接Zookeeper失败后会使用本地缓存的workerID.properties文件,但是这个文件只存了workId,没有存时间戳,所以还是存在潜在的时间回拨问题,我对这个问题进行了修复,并且增加了很多新的功能支持,你可以看看我的这个项目 https://github.com/NotFound9/Leaf
你好,我这里有另外一种处理时钟回拨的思路,具体参考的是:https://www.jianshu.com/p/b1124283fc43,在他的基础上我进行了修改,我的 fork:https://github.com/nekolr/Leaf/tree/ring_snowflake
你好,我这里有另外一种处理时钟回拨的思路,具体参考的是:https://www.jianshu.com/p/b1124283fc43,在他的基础上我进行了修改,我的 fork:https://github.com/nekolr/Leaf/tree/ring_snowflake
简书这篇文章里面写的代码是有问题的,单看这种方案的话, 好处也仅仅是时钟回拨时,可以复用一些之前剩余的ID,维持一小段时间,而且能维持的时间也取决于平常的获取ID的QPS,没有真正解决时钟回拨问题。 坏处是仅仅为了在发生时钟回拨时能多维持一段时间,就每次获取ID都需要去使用CAS操作更新数组,开销比较大。而且时间回拨后使用的这些ID的生成时间与实际获取时间不一致。
这种方案还不如为每一个正在运行的节点分配一个备用的机器ID,发生时间回拨时,如果回拨时间较短就休眠等待,回拨时间较长就使用备用的机器ID。使用备用ID时,再次发送回拨的话就抛出异常。
你好,我这里有另外一种处理时钟回拨的思路,具体参考的是:https://www.jianshu.com/p/b1124283fc43,在他的基础上我进行了修改,我的 fork:https://github.com/nekolr/Leaf/tree/ring_snowflake
简书这篇文章里面写的代码是有问题的,单看这种方案的话, 好处也仅仅是时钟回拨时,可以复用一些之前剩余的ID,维持一小段时间,而且能维持的时间也取决于平常的获取ID的QPS,没有真正解决时钟回拨问题。 坏处是仅仅为了在发生时钟回拨时能多维持一段时间,就每次获取ID都需要去使用CAS操作更新数组,开销比较大。而且时间回拨后使用的这些ID的生成时间与实际获取时间不一致。
这种方案还不如为每一个正在运行的节点分配一个备用的机器ID,发生时间回拨时,如果回拨时间较短就休眠等待,回拨时间较长就使用备用的机器ID。使用备用ID时,再次发送回拨的话就抛出异常。
CAS 操作与 Leaf 的同步获取 ID 相比,理论上来说相差应该不大吧。 生成时间与获取时间不一致会有什么问题吗?
时间不一致一般不会有什么问题,只是丧失了一些业务含义,如果一些业务要求id跟生成时间必须一直到话。这种方案跟普通的获取ID的方案有额外的判断和CAS操作存储ID的时间开销和内存开销,而且发生了时间回拨也无法真正解决问题,只是多维持了一段时间。
时间不一致一般不会有什么问题,只是丧失了一些业务含义,如果一些业务要求id跟生成时间必须一直到话。这种方案跟普通的获取ID的方案有额外的判断和CAS操作存储ID的时间开销和内存开销,而且发生了时间回拨也无法真正解决问题,只是多维持了一段时间。
感谢解答。
https://www.jianshu.com/p/b1124283fc43
这个解决方案需要依赖redis,是不是与原来雪花算法的初衷不一样了
https://www.jianshu.com/p/b1124283fc43
这个解决方案需要依赖redis,是不是与原来雪花算法的初衷不一样了
目前几乎所有的分布式id生成框架都是有依赖的,因为需要对不同机器上生成的分布式id进行区分,所以每个部署了Leaf服务的ip:port都会有一个workID,Leaf依赖于Zookeeper去给每个ip:port分配一个workID,百度的uid-generator每次机器启动时依赖于数据库的自增键,分配一个workID。只是依赖强弱的区别,Leaf框架目前来看启动时,运行期间都是依赖于Zookeeper的,虽然说运行期间Zookeeper挂了,可以继续运行,但是会导致当前生成id的最大时间戳不能上报,而百度的uid-generator只在启动时依赖数据库,因为每次启动时获得的workID是不同的,下次启动时不需要复用上次的workID。
如果你要做到没有依赖,只能是在项目中的property配置文件中写一个映射表,对每个会部署分布式id服务的机器IP:port对应一个workId,也就是我fork了Leaf项目后,开发的local模式 项目地址:https://github.com/NotFound9/Leaf 介绍文章:https://juejin.im/post/5eaea4f4f265da7b991c4c31