美文网首页
设计分布式唯一id生成

设计分布式唯一id生成

作者: 周群力 | 来源:发表于2021-07-11 18:38 被阅读0次

1. 生成全局唯一id

什么时候需要生成全局唯一id

db不帮你自动生成的时候。比如:

  • db做了分库分表,没帮你自动生成,你又需要一个全局唯一的业务id
  • 没走db,比如请求到了后端要生成一个traceId

如何设计全局唯一id生成服务

a. 不依赖第三方唯一id生成服务,利用业务db的特性来生成id
比如业务的“订单表”做了分库分表后,想要全局唯一的订单id,就让分库后每个库按不同的起点和步长做递增。这样订单系统就不用依赖发号服务了,自己解决问题


image

缺点是db扩缩容时候太复杂。
另一个思路是每个分表有一个前缀,在分表内自增
这样其实可以避免扩缩容麻烦的问题,比如sharding策略是预先分1000个表,每个表的id有个通用前缀,表内id自增

b. 非中心化方案,机器标识(比如mac地址)作为命名空间,通过命名空间保证唯一
比如:

  • UUID(有很多种,有用Mac地址的。https://baike.baidu.com/item/UUID/5921266?fr=aladdin
    不过拿来做db主键有些缺点,比如太长,比如没有趋势递增性,对B+ tree存储不够cache friendly

  • snowflake(时间戳+命名空间+序列号,时间戳放前面以便全局趋势递增)

c. 中心化方案,实现一个唯一id生成服务,基于写操作线性一致的存储
比如用mysql自增特性做个发号器服务
比如随机,往线性化存储里cas写,写成功就算申请到id
如果吞吐量过大、对存储有压力,可以在存储上面加个cache,预先从存储申请多个id(号段)。这个cache就不需要用redis等,起个java程序做进程内cache即可

2. 生成“趋势递增”的全局唯一id

什么场景需要趋势递增?

  • 对b+树类的db来说cache friendly
    不过这种场景其实没有全局趋势递增需求,可以分表递增,每个分表id为 sharding前缀+自增id。用不到全局趋势递增

  • 拿来排序查最新数据
    比如查最新消息,不用新增个时间戳字段、建索引,直接按id排序查最新的100条:

select * from message order by message-id limit 100

再比如nosql之类的在时间戳字段上加索引很难,分页查最新数据的时候,只想按id查
https://www.w3cschool.cn/architectroad/architectroad-distributed-id.html

方案

Q: 类snowflake算法基于时间戳+命名空间,时钟回拨怎么办?
(发生闰秒、NTP时钟同步等情况都可能导致时钟回拨)
a. 外接存储记录最新时间戳,检测回拨。比如美团外接了个zk
b. 最终往线性化存储里写的时候检测重复,重复就报错重来
c. 多加几个命名空间,让概率小到忽略不计

Q: snowflake里的workerId咋生成
a. 基于线性化存储
比如美团方案,外接一个zk,每个机器顺序取workerId(依赖机器);
但是这样太重了,可以把workerId换成业务id,思想是通过命名空间减少冲突概率,而不是绝对唯一

b. 没必要一定用机器id,本质上只是加个命名空间,加几个业务字段作为命名空间就行
我们之前用到的方案是id里面除了时间戳还加上一些uid、业务类型、随机数之类的字段,作为命名空间,减少冲突概率

3. 生成全局单调递增的唯一id

什么场景需要

  • 版本号类的需求,比如做diff、判断先后顺序等
  • 拿id排序,业务不接受趋势递增,要求严格递增

方案

Q: 分布式关系库能否自动生成全局单调递增的唯一id?
看Tidb的只是单机递增,没法保证全局单调递增:
https://docs.pingcap.com/zh/tidb/stable/auto-increment

4. 介于“趋势递增”和“全局单调递增”之间的保证

“趋势递增”和“全局单调递增”这两种保证处于两个极端,能否给出介于两者之间的保证?

  • sharding内单调递增
    比如mysql分表后,每个分表sharding内递增
    比如上文说的Tidb

  • 单Insert语句内单调递增

  • session内单调递增

  • 单client所有请求生成的id单调递增
    以上两个用Lamport timestamp可以实现,得到的全序id符合因果序

Reference

架构 细聊分布式ID生成方法
Leaf——美团点评分布式ID生成系统
https://www.liaoxuefeng.com/article/1280526512029729

相关文章

  • 生成分布式序列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生成

    1. 生成全局唯一id 什么时候需要生成全局唯一id db不帮你自动生成的时候。比如: db做了分库分表,没帮你自...

  • 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生成规则部分硬性要求?目标出现...

网友评论

      本文标题:设计分布式唯一id生成

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