基于Redis解决集群环境下雪花算法机器号的分配问题

2021-08-13 15:12:30 浏览数 (1)

前言

如果你正在寻找一种全局唯一ID生成策略,那么我相信你一定会了解到一种算法,那就是雪花算法,如果再深入了解一下,你会发现雪花算法其实不单单只是一种算法,同时也是一种思想,它将ID细分为时间戳、机器号、序列号等几个关键部分。时间戳用来保持ID的递增趋势,机器号用来区分相同时刻下不同机器所生成的ID,序号用来区分同一个机器相同时刻下生成的ID。关于雪花算法的实现网上有很多现成代码可以借鉴,同时你也可以基于这种思想自己实现一个雪花算法。

如何实现自定义的雪花算法?

无论是自己实现的雪花算法还是网上借鉴的雪花算法,在集群环境中都面临着一个问题:在什么地方维护机器号?

  1. 代码中写死:这是最简单粗暴的方法,同时弊端也非常明显,那就是在切换到集群环境时会有重复ID产生的可能性。
  2. 写在配置文件中:这种方法看起来稍微优雅一些,但是也存在着明显的弊端,那就是每次发布版本时都要更改配置文件中的机器号
  3. 存在zookeeper中:这种方式是最理想的方式,在应用启动时注册一个临时节点,当应用关掉后,临时节点会自动删除,这样一来就可以进行机器号的复用

前两种方案不符合预期,第三种方案需要引入zookeeper中间件,成本过高,于是这三种方案都被我Pass了,苦思冥想了好几天,终于找到了一个相对轻量级的替代方案——基于redis实现。

基于Redis自动获取机器号

首先列出我的需求,我希望系统中的雪花算法实例可以满足如下场景

  1. 每次发布版本时,不需要手动维护雪花算法机器号
  2. 一个机器号在同一时刻只能由一个雪花算法实例所使用
  3. 雪花算法实例关闭后可以释放掉占用的机器号,以供其他实例使用

受到Redission思路的启发,可以在应用启动时向redis注册一个未使用的机器号并设置过期时间,然后再通过一个线程定时续约,这样一来就可以满足上述场景了。具体过程如下

注册机器号

  • Snowflake对象是对雪花算法机器号的一层封装,包含了机器号、ip地址、更新时间、创建时间等相关信息。
  • @DistributedLock是一个自定义注解,通过AOP实现了对Redission的封装,主要用来防止多个应用同时启动时机器号冲突的问题

机器号续约

总结

此方案应该可以满足绝大多数场景,略微有些不足之处是时效性不强,系统down机后要经过一段时间才会释放机器号(上述例子中是两小时)。如果在机器号失效期间内频繁发包也会导致无机器号可用的情况。此时可以根据需要自行调节机器号有效时间以及续约的时间间隔。

尾言

我的公众号是《敲得码黛》,一个不知名的IT程序员,欢迎大家关注我的个人公众号,一起学习,一起成长!

0 人点赞