分布式ID

需求

  • 全局唯一
  • 高性能
  • 高可用
  • 简单易用

UUID

优点:

  • 唯一
  • 不依赖于任何第三方服务

缺点:

  • 是字符串类型而非数字,不满足数字ID的需求
  • 字符串太长了,DB查询效率受影响

数据库自增ID

如果使用 mysql 单实例:性能可能不够;单实例的稳定性不强,宕机会影响业务

如何解决稳定性问题呢?

方案一:使用主从模式集群

存在的问题:满足了高可用,但数据同步延时问题可能导致ID重复。

方案二:使用多主机主从模式集群,对多主机做高可用

必须设置自增起始值与步长
举例:比如两个主机 master1 只会产生奇数ID,master2 只会产生偶数ID

存在的问题:

  • 性能依旧不足,每次都去请求数据库
  • 如果再新增一个主,扩展起来麻烦

如何解决性能问题呢?

方案三:使用号段模式,批量从数据库获取ID缓存起来,缓存中的ID一旦达到上限就再次去数据库批量获取

DB设计如下:
image

  • biz_type 代表业务类型,业务隔离
  • max_id 代表当前最大的可用 id
  • step 代表号段的长度,合理设置即可
  • version 是一个乐观锁,用来保证并发更新的正确性

最终方案

最终方案结合方案二和方案三的优点,DB设计如下:
image

  • delta 表示缓存中的 ID 每次增量
  • remainder 代表余数

缺点:

  • 扩展主机个数麻烦
  • 实现复杂

雪花算法

  • 使用一个 long 类型作为 ID
  • 64位:第一位0表示正数 + 41位毫秒级时间戳 + 10位主机编号 + 12位序列号
  • 时间戳通常是相对时间,这样可用期限就更长,理论上支持 69 年
  • 支持 1024-1=1023 个主机节点
  • 支持同一个时间点同一台服务器生成 4096-1=4095 个序列号

主机编号手动分配太麻烦了,可以在 Zookeeper 中创建序列节点,用节点序号(缓存起来)作为主机编号。

优点:快


相关文章:

//www.liaoxuefeng.com/article/1280526512029729

//www.cnblogs.com/wuneng/p/11478160.html

//github.com/didi/tinyid/wiki/tinyid原理介绍

//mp.weixin.qq.com/s/hz7TntFDurwkAaSGODbF-Q

Tags: