美文网首页
分布式唯一ID生成

分布式唯一ID生成

作者: 萧然AND沐橦 | 来源:发表于2020-03-30 13:46 被阅读0次

设计目的:

在分布式条件下,生成唯一ID,速度快

要求:

  • 长度8字节,首位不能使用,故只能使用63bits

  • 全局唯一

设计思路:

由于不是集中分配,所以每台机器必须唯一,生成过程中必须要有机器唯一的信息,可以使用:

  1. 每个机器分配一个唯一机器ID,需要外部机制的依赖如etcd

  2. 取MAC地址(太长了128bits)

  3. 取IP地址(可能冲突,不同机器的子网ip可能冲突)

设计参考:

思路,按照生成uuid的思路生成,参考twitter的snow-flake算法来生成

格式
  • tag:1bit,不使用

  • physic delta time:31bits,当前物理时间的秒-Base时间秒值,最大支持到68年以后,按照某一时间点为Base时间(如项目上线时间),可以hard code到代码中。

  • worker node id:12bits,每个进程用的唯一标识 ID

  • sequence id:20bits,1s内自增

提供的性能:

每秒最大理论提供获取104w个id生成。

难点及解决:

会出现的问题 解决方案
A. 如果当前时间⼩于记录的上⼀个秒值,则说明这台机器的时钟回拨了 更换worker id
B. 如果当前时间等于记录的上⼀个秒值,则说明这台机器的时钟回拨了 ⾃旋⾄下⼀秒
C. 如果这台机器的系统时间在启动之前回拨过,那么有可能出现ID重复的危险 可以重启时候使⽤与上次不同的worker id来避免确定时钟可能回拨的最⼤值,为了防⽌重复id分配,可以等待最⼤回拨时间后分配确定时钟可能回拨的间隔时间,保证不会连续出现回拨!
D. 最后⼀次获取的ID值是否需要保存 可以通过上⾯⽅法C避免持久化保存

(每次启动使⽤不同的worker id弊端:从ID不能确定是哪⼀个机器的进程发送的事务请求。)

限制因素的处理:

由于集群中时钟回拨的时间和次数很难确定,所以我们倾向每次使用不同的worker id来回避这个问题。

这里我们会强依赖Etcd,用来保存进程 的worker id信息和已分配worker id的map。

实现思路如下:

  1. 每个进程在启动的时候,都会生成一个uuid,将此ID作为唯一键,Value为当前进程的worker id,并且维持续Lease

  2. 维护一个已分配的worker id的bitmap,由于worker id最大为4096,故该bitmap需要空间4096/8 bytes = 512bytes,用来标记已分配的worker id情况。

  3. 程序每次启动时,需先waitNextSecond(或者0.5s,这个wait时间可以自己根据实际情况需求设定),保证多次重启的情况下,能够有进程的Lease失效。

    每次分配的流程如下:

    1. 都先获取现在集群中所有的进程的worker id分配信息,和该bitmap

    2. 找出目前已分配到了最大worker id值,在此基础上+1操作,作为此次分配的worker id

    3. 计算出新的bitmap,用Etcd的事务,写入该bitmap到Etcd中,如果事务失败,重新启动整个流程

    4. 之后,将自己的uuid作为键,此次分配的worker id作为value,写入到Etcd中,并且维持续Lease

    5. 过程中如果失败,重新启动整个流程

由于bitmap的延后清除,即当存在已经挂了的进程时,即使其Lease最终消失,但bitmap中仍旧会存在其已经占用,此时我们保持向后递增分配,就可以绕过当前已存在的worker id,保证不会立即复用编号较小的worker id。

由于步骤3会重新生成bitmap,以此来保证Lease已经消失的进程的worker id,可以被回收掉。

我们保证使用最大值+1来分配worker id,如果已经存在到达了4095的worker id我们需要回环去找。即最大值回环向右第一个当前未使用的worker id。并且用Etcd事务保证了更新bitmap的原子性。

正确性分析:

  • Lease ,worker id过期时间

  • t,重启一次进程,开始获取worker id前等待时间

  • N,Lease时间内重启次数为

  • n,集群内进程数量

  • Range,Worker Id 分配区间

那么,在Lease时间内,单个进程能够重启的次数为:

N = Lease / t ;

那么n个进程,在Lease时间内,可以重启的次数为:

C = N * n ;

即,C = Lease / t * n

C的值的含义就是,在Lease时间内可能消耗掉的worker id的数量最大值。

那么我们只要保证 C < Range 就可以保证Lease时间内是有足够的worker id可以分配给集群中的进程。

举例:

Range = 4096; 分配worker ID 的区间

n = 100 ; 集群中进程数量为 100 个

Lease = 5 s;worker id 的 Lease 时间

t = 0.5 s ; 重启等待时间0.5s

由此,计算出来C的值为:C = 5 / 0.5 * 100 => 1000

4096 > 1000 ,可以满足Lease内的分配需求。

允许的最大时钟跳变:

即最后一次分配worker id复用了第一次分配的worker id经历的时间,也即 worker id 的Range 在多少秒会被使用完。

我们假设集群中的进程断重启。那么理论上,在Range用完时(不回收worker id),可以重启的总次数为:

MaxRestartCount = Range / n ;

重启花费的总时间为:

ReverseTimeCount = MaxRestartCount * t ;

(Lease 必须小于 ReverseTimeCount ,这样 再次循环使用第一次分配的worker id时,才可用。)

故,我们允许的最大时钟跳变为 ReverseTimeCount

举例:

目前我们的Range为【0,4096),也就是可以分配4096个worker id,即 Range = 4096 ;

假设集群中存在100个进程,即 n = 100 ;

假设重启一次时间为0.5s,即 t = 0.5 s

故 ReverseTimeCount = Range/n * t = 20.48 s

允许的最大时钟跳变为 20.48 s 已满足大多数场景

算法的限制条件:

  1. 对集群内的进程数量有限制要求
  2. 对于允许的最大时钟跳变时间有限制
  3. 强依赖Etcd

假设,一个集群4个进程,也就是 n = 4 。

假设我们的Lease 为5 s,重启等待时间为0.5s

那么允许的最大时钟跳变:
(假设目前worker id的数量是4096个)
ReverseTimeCount = 4096 / 4 * 0.5 = 512 s

Lease 内 最大消耗的worker id 数量为:

C = 5 / 0.5 * 4 = 40 个

要保证一个Lease不能消耗完所有worker id并且根据集群时钟同步状况,来控制允许的最大时钟跳变。

如果集群中进程是1000个,那么
C = 5 / 0.5 * 1000 = 10000 ,10000大于4096 ,这个超过了worker id的分配范围。所以此时必须调整 重启等待时间,调长一些。

此时允许的最大时钟调变:
ReverseTimeCount = 4096/1000*0.5 = 4 * 0.5 = 2 s

The End ;

相关文章

  • 生成分布式序列ID

    生成分布式序列ID 介绍 在很多分布式系统中,需要生成唯一的id。如在分库分表的情况下,给某个逻辑表生成唯一id。...

  • 分布式唯一Id(雪花算法),原理+对比+方案

    集群高并发情况下如何保证分布式唯一全局Id生成 为什么需要分布式全局唯一Id,以及分布式Id的业务需求 在复杂分布...

  • 从给apache sharding-sphere提交的issue

    很多的分布式系统的唯一ID都是基于雪花算法生成的,apache sharding-sphere的分布式ID也是采用...

  • id-generator 分布式ID生成器

    1、概述 id-generator分布式ID生成器, 解决在分布式系统唯一性标识生成复杂、不统一的问题,如数据库分...

  • UUID

    IdWorker.java 高并发分布式系统中生成全局唯一Id汇总 Twitter的分布式自增ID算法snowf...

  • ID生成器

    分布式唯一ID生成器https://www.liaoxuefeng.com/article/12805265120...

  • Laravel snowflake 使用Twitter的Snow

    Laravel扩展包,实现 Snowflake 生成分布式唯一 ID laravel-snowflake Lara...

  • 分布式系统生成唯一ID的几种方式

    在分布式系统中常会需要生成系统唯一ID,生成ID有很多方法,根据不同的生成策略,以满足不同的场景、需求以及性能要求...

  • 高并发下如何生成唯一ID

    通过本文档你将学习到 为什么需要分布式全局唯一ID以及分布式ID的业务需求 ? ID生成规则部分硬性要求?目标出现...

  • 04.分布式系统的id生成方式

    分布式ID需要满足那些条件? 全局唯一:必须保证ID是全局性唯一的,基本要求高性能:高可用低延时,ID生成响应要块...

网友评论

      本文标题:分布式唯一ID生成

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