无锁唯一id生成

Posted fbw-gxy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无锁唯一id生成相关的知识,希望对你有一定的参考价值。

首先关于唯一id生成,个人比较推崇美团的Leaf,具体介绍可见链接:

https://tech.meituan.com/2017/04/21/mt-leaf.html

但这个框架未免有些太重了,笔者之前看到项目中生成方式是时间戳(精确到秒)+四位随机(数字+字母)的方式,看起来简单轻巧,但在高并发场景遇到了重复的情况,为了不改变原有的唯一id的结构,笔者把心思动在了多台机器对同一种业务,如何保证后四位随机数不重复上,毕竟34(0到9,大写字母排除I和O)^4大概有100W个数字,一秒并发超过100W的话只能修改原id结构中时间戳精确到毫秒,如果一毫秒并发超过100W,这大概是一秒1个亿的量级,其实可以吧四位随机字母改成6位,此时是1秒1000亿的量级,暂时应该没有业务并发量能有这个级别吧。

言归正传,关于如何保证多级四位字母不重复上,首先我们吧这个问题转换成如何保证多级四位34进制的数字不重复,转换为10进制就是如何保证多机对一个100W以内的数字不重复。最简单的方式当然是redis自增,但这样每次获取id都要连接一次redis,未免有些太过耗时

为了解决上述问题,我们可以引入atomicLong,并把1000W分成1000个数字*1000组,每个机器初始取的一个所在组,然后本地使用atomicLong自增,我们取它与1000的余数作为当前数字,当次数字达到999,则在redis触发一次自增,其他情况只要atomicLong自增即可。这样多台机器在每秒100W的id生成量以内,都不会产生重复。

最后我们聊一下同一秒内唯一id太密集的情况,对此我们可以采取已组做尾数,atomicLong*1000组合成数字的方式,并引入栅栏加密,最后打乱字母与数字顺序的方式。

当然问题也有以下几点:

1、强依赖redis,一旦redis出现问题,atomicLong达到999后,下一次生成必定失败,并且单台机器后续吞吐量只能达到每秒1000

2、如果生产有20台机器,其中一台机器初始化所在组后,产生网络问题导致后续请求均未到达此机器,问题修复后可能出现此机器组别与其他机器重复,导致id重复的情况

当然以上两种情况相对都是小概率事件,同事我们还有时间戳保证id的唯一性,所以可以在很大程度上忽略此问题,最后附上核心代码如下图:

技术图片

 

以上是关于无锁唯一id生成的主要内容,如果未能解决你的问题,请参考以下文章

如何生成唯一的Android设备ID

唯一ID生成算法剖析

唯一ID生成算法剖析

Redis-全局唯一ID

如何用redis来生成唯一Id

系统设计分布式唯一ID生成方案总结