Skip to content
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

leaf snowflake真的解决了时钟回拨引起的重复id问题了吗 #216

Open
miles-ton opened this issue Apr 14, 2024 · 1 comment
Open

Comments

@miles-ton
Copy link

举一个栗子:
后台线程每3s会将机器的当前时间同步到zk。假设现在是第9s,后台线程刚刚同步了时间到zk。然后过了2s,并且这两秒有id被发出去。此时机器重启,并且同时发生了时钟回拨,回拨了1s。
leaf snowflake启动的时候会把当前机器时间和zk的上次注册时间做对比,如果小于上次注册时间能判断出发上了回拨,由于这次回拨只回拨了1s,也就是当前机器时间是第10s,是大于第9s的,所以启动能正常启动。然后会继续用第10s做id分发。
现在问题来了,在重启之前实际上是以及分发了2s的id了,也就是说第11s之前的id都以及被分发过。但是重启之后又从10s开始分发id,这个时候不就导致id被重复分发了吗?
求大佬解答一下这个疑问

@spider523
Copy link

spider523 commented Nov 18, 2024

根据美团技术文档关于lead snowflake的介绍:Leaf——美团点评分布式ID生成系统,如下:

服务启动时首先检查自己是否写过ZooKeeper leaf_forever节点:

若写过,则用自身系统时间与leaf_forever/${self}节点记录时间做比较,若小于leaf_forever/${self}时间则认为机器时间发生了大步长回拨,服务启动失败并报警。
若未写过,证明是新服务节点,直接创建持久节点leaf_forever/${self}并写入自身系统时间,接下来综合对比其余Leaf节点的系统时间来判断自身系统时间是否准确,具体做法是取leaf_temporary下的所有临时节点(所有运行中的Leaf-snowflake节点)的服务IP:Port,然后通过RPC请求得到所有节点的系统时间,计算sum(time)/nodeSize。
若abs( 系统时间-sum(time)/nodeSize ) < 阈值,认为当前系统时间准确,正常启动服务,同时写临时节点leaf_temporary/${self} 维持租约。
否则认为本机系统时间发生大步长偏移,启动失败并报警。
每隔一段时间(3s)上报自身系统时间写入leaf_forever/${self}。

对于上面的问题,我的理解是即使本节点判断时间是有效的,但是本节点会获取其他节点时间做进一步的时钟回拨检测,因此这种情况也是能够判断的。当然,这里有一个前提,还有其他的节点,这对于实际的情况一般是满足的,因为考虑到高可靠性,生产环境都会部署多个leaf节点。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants