011 分布式统一ID生成策略-预加载方式和节点生成方式

        统一ID生成服务,不是那么好去构建的,需要更深入的去进行思考,包括使用Redis生成ID,在高并发下多个服务去访问,读写分离的情况下如果延迟导致读写不一致,会不会出现其他的问题等等。

第一种:业界比较主流的分布式ID生成器的策略是提前加载,也就是预加载的机制,我们可以预先生成一批唯一的ID,然后直接放到内存里,由服务的调用方直接获取就好,获取之后就直接进行删除,ID使用过半的时候或者达到临界值的时候再进行生成一批ID。这有点类似于高性能的一些框架中的内存预加载,或者一些内存计算、流式计算中spark里的预加载机制。看来在软件设计的领域,所有的思想都是相通的。

当然,如果统一ID生成服务的ID生成策略想要加入具体的业务规则,我们可以预先进行一些配置,比如订单服务、物流服务、支付ID等等,在获取ID的时候可以加一些生成的业务规则,这些都是可以在统一生成服务的后台进行配置

批量生成的ID存储在内存中,内存技术可以是spring cache、ecache实现;

第二种(要考虑业务是否适合):使用单点唯一的ID生成策略,也就是我们固定的一个机器节点来生成一个唯一的ID,这种方式的好处是可以做到全局唯一,主要还是通过拼接的方式去实现的

比如我们每一个真实的线上服务节点都要有一个唯一的机器码,然后采用组合的方式进行生成:机器码 + 时间戳 + 自增序列 + 其他业务规则。当然也可以使用其他的组合方式,只不过大家需要注意的一点就是服务器时间的NTP问题,也就是服务器时间的同步问题.

NTP问题描述以及使用自增序列解决NTP问题

NTP是网络时间协议(Network Time Protocol),它是用来同步网络中各个计算机的时间的协议.

在高并发的场景下,我们的生成ID请求量非常的巨大,就会暴露出NTP的问题。

举个例子,如果单纯的采用: 机器码 + 时间戳  或者 机器码 + UUID 这种组合,在高并发下可能会有订单重复的问题。

机器码: ABK007

当前时间戳:1528018092517

ID生成为: ABK0071528018092517                

NTP就是你的服务器系统的时间会定时去获取,然后进行更新校准,也就是说,我们现在的系统时间是:1528018092517

生成了一个IDABK0071528018092517的订单,紧接着我们的服务器进行了NTP的时间校准,这个时候系统时间肯定是向前走的,比如我们在校准前的一刻,系统时间为:1528018092530 ,恰巧我们的服务器时间走的比较快,然后经过了一次NTP服务时间校准,我们的系统时间可能就会回到从前,回到过去.. 回到我们生成订单的时间之前,比如为1528018092513,那么高并发下在后续的订单id生成的时候可能还会生成一个订单为: ABK0071528018092517 ,这个时候我们就会产生订单id重复问题。

所以,我们要解决高并发下的NTP问题就要考虑周全:

比如使用:机器码 + 时间戳 + 自增序列,即时是我们的时间戳被NTP服务校准产生回调,那么我们自增系列永远会在单点下保证自增,比如AtomicLong就是很好的一种原子自增序列计数器。

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值