美文网首页
7. 分布式统一ID策略与Disruptor作用

7. 分布式统一ID策略与Disruptor作用

作者: 香沙小熊 | 来源:发表于2021-06-24 17:14 被阅读0次

    1.业务ID生成方式与含义

    使用带有业务含义的ID生成策略,这种方式也在传统应用系统、特定的场景下非常的好用。比如我们现在有一张商品货架表,这张表的数据维度是这样的,比如是按照城市和区域来划分的。

    •比如北京我们按照100000为基本维度数据,100010为北京的一个区域,100020则为另一个区域,以此类推,200000可能是另一个城市,200010 则为另一个城市的区域。那么我们在生成货架信息ID的时候,可以按照前六位为城市和区域的方式进行组织,后面可以拼接一个简单的32位UUID字符串:

    image.png
    前8位都是具有业务含义的:前四位为城市维度编码,第五、六位为区域维度编码,最后两位为货架类型编码。

    从前六位来看,这四条数据其中前三条数据属于一个城市下的数据信息,那么我们查询一个城市下的货架数据,查询语句可以为:

    select * from goods_shelf gs
    where id > '10001000000000000000000000000000000000'
      and id <'20000000000000000000000000000000000000'
    
    image.png

    如果想要查询1000(北京)这个城市下10区域的数据,则查询语句如下:

    select * from goods_shelf gs
    where id > '10001000000000000000000000000000000000'
     and id <'10002000000000000000000000000000000000'
    
    image.png

    那么我们如果想查询北京这个城市下面第一个区域的类型为01的货架集合,sql语句如下:

    select * from goods_shelf gs
    where id > '10001001000000000000000000000000000000000'
      and id < '10001002000000000000000000000000000000000'
    
    
    image.png

    2.Redis生成分布式统一ID问题

    Redis缓存,利用Redis的分布式锁去解决此类问题.首先第一点,Redis本身也会有性能问题,在超高的并发下可能会有延迟等一些细节问题,第二点我们的服务调用链过长,我们的服务调用可能失败,因为期间过程是调用统一ID生成服务,然后再去Redis里set id,可能会出现重复情况,那么就需要进行重试。
    延迟或重试可能会发生服务调用超时问题,导致我们的服务调用失败。


    image.png

    高并发下可能会指定核心业务超时时间 50ms内
    而Redis服务重试时间可能 达到150ms+
    直接就报超时了

    3.业界主流分布式统一ID生成策略

    实现一:提前加载,也就是预加载的机制

    预加载机制,其实现核心如下:

    1. 提前加载,也就是预加载的机制
    2. 并发的获取,采用Disruptor框架提升性能
    实现二:单点生成方式

    单点生成方式,其核心实现如下:

    1. 固定的一个机器节点来生成一个唯一的ID,好处是能做到全局唯一
    2. 需要相应的业务规则拼接:机器码 + 时间戳 + 自增序列
      注意:但是要注意NTP服务器问题
    为什么要进行拼接自增序列

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

    NTP是网络时间协议(Network Time Protocol),它是用来同步网络中各个计算机的时间的协议
    举个例子,如果单纯的采用:机器码+时间戳 或者 机器码+UUID这种组合,在高并发下可能会有订单重复的问题。


    例:
    机器码:ABK007
    当前时间戳 1624520050000
    ID生成为:ABK0071624520050000


    NTP就是我们的服务器系统的时间会定时去获取,然后进行更新校准,也就是说,我们现在的系统时间是:1624520050001(ABK007)
    生成了一个ID为:ABK0071624520050001的订单


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

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

    注意:实际生产环境中最好采取预加载的机制 + 单点生成方式(兜底)保持高可用
    当预加载的机制不可用时,立即切换到单点生成方式
    1. 每一次预加载的生成Pre-MaxId (Pre-MaxId > db中 MaxId),存到Redis或者DB中
    2. Pre-MaxId为基础,结合单点生成方式的分布式Id也是唯一的。

    4.Disruptor在分布式统一ID的使用

    image.png

    Disruptor负责生产和消费分布式id,提高性能

    特别感谢:

    阿神

    相关文章

      网友评论

          本文标题:7. 分布式统一ID策略与Disruptor作用

          本文链接:https://www.haomeiwen.com/subject/tgewyltx.html