前言
如果你正在寻找一种全局唯一ID生成策略,那么我相信你一定会了解到一种算法,那就是雪花算法,如果再深入了解一下,你会发现雪花算法其实不单单只是一种算法,同时也是一种思想,它将ID细分为时间戳、机器号、序列号等几个关键部分。时间戳用来保持ID的递增趋势,机器号用来区分相同时刻下不同机器所生成的ID,序号用来区分同一个机器相同时刻下生成的ID。关于雪花算法的实现网上有很多现成代码可以借鉴,同时你也可以基于这种思想自己实现一个雪花算法。
无论是自己实现的雪花算法还是网上借鉴的雪花算法,在集群环境中都面临着一个问题:在什么地方维护机器号?
-
代码中写死:这是最简单粗暴的方法,同时弊端也非常明显,那就是在切换到集群环境时会有重复ID产生的可能性。 -
写在配置文件中:这种方法看起来稍微优雅一些,但是也存在着明显的弊端,那就是每次发布版本时都要更改配置文件中的机器号 -
存在zookeeper中:这种方式是最理想的方式,在应用启动时注册一个临时节点,当应用关掉后,临时节点会自动删除,这样一来就可以进行机器号的复用
前两种方案不符合预期,第三种方案需要引入zookeeper中间件,成本过高,于是这三种方案都被我Pass了,苦思冥想了好几天,终于找到了一个相对轻量级的替代方案——基于redis实现。
基于Redis自动获取机器号
首先列出我的需求,我希望系统中的雪花算法实例可以满足如下场景
-
每次发布版本时,不需要手动维护雪花算法机器号 -
一个机器号在同一时刻只能由一个雪花算法实例所使用 -
雪花算法实例关闭后可以释放掉占用的机器号,以供其他实例使用
受到Redission思路的启发,可以在应用启动时向redis注册一个未使用的机器号并设置过期时间,然后再通过一个线程定时续约,这样一来就可以满足上述场景了。具体过程如下
注册机器号
-
Snowflake对象是对雪花算法机器号的一层封装,包含了机器号、ip地址、更新时间、创建时间等相关信息。 -
@DistributedLock是一个自定义注解,通过AOP实现了对Redission的封装,主要用来防止多个应用同时启动时机器号冲突的问题
机器号续约
总结
此方案应该可以满足绝大多数场景,略微有些不足之处是时效性不强,系统down机后要经过一段时间才会释放机器号(上述例子中是两小时)。如果在机器号失效期间内频繁发包也会导致无机器号可用的情况。此时可以根据需要自行调节机器号有效时间以及续约的时间间隔。
尾言
我的公众号是《敲得码黛》,一个不知名的IT程序员,欢迎大家关注我的个人公众号,一起学习,一起成长!
原文始发于微信公众号(敲得码黛):基于Redis解决集群环境下雪花算法机器号的分配问题
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/28414.html