分布式唯一ID生成方案

分布式唯一ID特点

1、全局唯一 : 不能重复

2、趋势递增:在MySQL InnoDB引擎中使用的是聚集索引,使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应尽量使用有序的主键保证写入性能

3、单调递增 :保证下一个ID一定大于上一个ID

4、信息安全 :防止从连续ID中泄露信息

5、高可用性:低延时、高QPS、高可用

分布式唯一ID生成方法

1、UUID

UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写

UUID的标准形式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的32个字符,如:550e8400-e19b-41d4-a716-446655440000

优点:本地生成,速度快,无网络消耗

缺点:无序,不利于排序查询

2、数据库生成唯一ID

方案一:(主库生成)使用数据库的auto_increment属性,每次设置ID的值就使用LAST_INSERT_ID来设置

优点:简单,保证唯一,保证递增

缺点:单点写,主库的写性能决定了ID生成性能,难以扩展,依赖主库,可用性差

方案二:(多库共同生成),每个id生成服务器设置一个不同的起始值,同时设置相同的步长

优点:提高了可用性

缺点:每次都需要去数据库取ID,性能会成为瓶颈

方案三:(多库+缓存 共同生成)添加内存缓存,每次取一批放入内存,再使用线程安全的原子操作进行分发即可

优点:性能得以提高

缺点:一旦服务器故障导致内存中的段丢失,需要重新申请,导致ID的不连续

3、Redis生成唯一ID

Redis是单线程的,所以可以用来生成全局唯一的ID,可以用redis的RedisAtomicLong生成自增的ID值

Redis可以满足全局ID趋势增长的要求,如果有多台redis服务器,我们可以根据不同的增长数和初始值来设定,这样,即使是不同的服务器也不会有重复的ID

优点:性能优于数据库,ID天然排序

4、类Snowflake生成唯一ID

Snowflake是Twitter开源的分布式算法,一个long型的ID组成:

1、1位标识符,通常为正数

1、41bit的毫秒数(可以表示69年)

2、10bit的机器编码(可以表示1024台机器,一般前5代表数据中心ID,后5位是某个数据中心的机器ID)

3、12位的毫秒内计数(同一机器在同一毫秒内最多产生2^12个,多余的要等到下一毫秒生成)

这个算法单机每秒内理论上最多可以生成1024*(2^12),也就是400w个ID

优点:快,实现简单

缺点:各个服务器之间由于没有全局时钟,无法完全保障时间统一,如果发生回拨会产生重复ID

时钟回拨解决方案

snowflake算法强依赖于时间,如果时间发生回拨,有可能会生成重复ID,在生成nextId时如果当前时间小于上一次时间则一定发生了时钟回拨,普通算法会直接抛出异常,在这里我们可以对其进行优化

1、如果回拨时间小于配置阈值,那么可以选择直接等待一定的时间,让机器的时间追上来

2、如果回拨时间较长,无法接受长时间的阻塞,可以增加一个扩展位,当发生时钟回拨时,直接在扩展位加1,2位的扩展位允许我们3次回拨时钟,如果超出扩展位,可以选择抛出异常。

分布式唯一ID生成实例

Leaf方案

1、Leaf-segment

优点:号段有缓存,有一定容灾性,加锁控制,线程安全

缺点:服务重启后,id可能会跳动,当segment使用完后,还是需要数据库IO,tp999数据会偶尔出现尖刺。

segment双buffer优化

Leaf的取号时机是在号段消耗完的时候进行的,这就意味着号段的下发时间取决于从DB取回号段的时间,在此期间,其他的请求会阻塞,为了减少这种阻塞,不需要在db取号段的时候阻塞请求线程,即当消费到某个点时就异步地把下一个号段加载到内存中,而不需要等到号段用尽才去更新号段,这样就可以很大程度上降低系统的TP999指标。

2、Leaf-snowflake

Leaf-snowflake方案完全沿用snowflake方案的bit位设计,即是“1+41+10+12”的方式组装ID号,workerID的分配使用Zookeeper持久顺序节点的特性自动对snowflake节点配置workerID

1、启动leaf-snowflake服务,连接zookeeper,在leaf_forever父节点下检查自己是否已经注册过。

2、如果有注册过,直接取回自己的workID(zk顺序节点生成的int类型ID号)启动服务。

3、如果没有注册过,就在该父节点下创建一个持久顺序节点,创建成功后取回顺序号当作自己的workerID号,启动服务。

弱依赖zk

除了每次去zk拿数据意外,也会在本机系统缓存一份workID,当zk出现问题,能保证服务正常启动

时钟回拨

如果时间偏差小于5ms,则等待两倍时间,如果还是小于,抛异常并上报。

参考:

1、https://zhuanlan.zhihu.com/p/88410901

2、https://www.cnblogs.com/jiangxinlingdu/p/8440413.html

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

发布了28 篇原创文章 · 获赞 9 · 访问量 4664

猜你喜欢

转载自blog.csdn.net/chixi123/article/details/103866521