目录

一、什么是分布式ID?

二、为什么需要分布式ID?

三、如何生成分布式ID?

1. 要求

2. 解决方案

2.1 基于数据库

2.2 基于算法

3. 开源框架

3.1 UidGenerator(百度)

3.2 Leaf(美团)

3.3 Tinyid(滴滴)


一、什么是分布式ID?

日常开发中,我们需要对系统中的各种数据使用 ID 唯一表示,比如用户 ID 对应且仅对应一个人,商品 ID 对应且仅对应一件商品,订单ID对应且仅对应一个订单。

我们现实生活中也有各种 ID,比如身份证 ID 对应且仅对应一个人、地址 ID 对应且仅对应

简单来说,ID 就是数据的唯一标识

分布式 ID 是分布式系统下的 ID。

二、为什么需要分布式ID?

随着系统的数据量越来越大,单机MySQL已经没办法支撑了,需要进行分库分表。

对数据库分库分表之后, 数据遍布在不同服务器上的数据库,数据库的自增主键已经没办法满足生成的主键唯一了,此时我们就需要生成分布式 ID了。

三、如何生成分布式ID?

1. 要求

一个最基本的分布式 ID 需要满足下面这些要求:

  • 全局唯一 :ID 的全局唯一性肯定是首先要满足的!
  • 高性能 : 分布式 ID 的生成速度要快,对本地资源消耗要小。
  • 高可用 :生成分布式 ID 的服务要保证可用性无限接近于 100%。
  • 方便易用 :拿来即用,使用方便,快速接入!

除了这些之外,一个比较好的分布式 ID 还应保证:

  • 安全 :ID 中不包含敏感信息。
  • 有序递增 :如果要把 ID 存放在数据库的话,ID 的有序性可以提升数据库写入速度。并且,很多时候 ,我们还很有可能会直接通过 ID 来进行排序。
  • 有具体的业务含义 :生成的 ID 如果能有具体的业务含义,可以让定位问题以及开发更透明化(通过 ID 就能确定是哪个业务)。
  • 独立部署 :也就是分布式系统单独有一个发号器服务,专门用来生成分布式 ID。这样就生成 ID 的服务可以和业务相关的服务解耦。不过,这样同样带来了网络调用消耗增加的问题。总的来说,如果需要用到分布式 ID 的场景比较多的话,独立部署的发号器服务还是很有必要的。

2. 解决方案

2.1 基于数据库

(1)数据库主键自增

通过关系型数据库的自增主键产生来唯一的 ID。

(2)数据库号段模式

批量获取,存在内存里,用的时候直接从内存里获取。

解决了数据库主键自增方案每次获取 ID 都要访问一次数据库的问题。

(3)Redis自增

通过 Redis 的 incr 命令即可实现对 id 原子顺序递增。

2.2 基于算法

(1)UUID

包含 32 个 16 进制数字(8-4-4-4-12),其生成规则包括 MAC 地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素。

(2)Snowflake

生成一个long类型的ID,一个long大小8字节,一个字节8个比特位,因此它使用64个比特位来确定一个分布式ID。其中1bit为标识位,41bit代表时间戳,10bit标识一台机器,12bit则用来标识每个id。

分类 方案 优点 缺点
数据库 数据库主键自增

1)实现起来比较简单

2)ID 有序递增

3)存储消耗空间小

1)支持的并发量不大

2)存在数据库单点问题(可以使用数据库集群解决,不过增加了复杂度)

3)ID 没有具体业务含义

4)安全问题(比如根据订单 ID 的递增规律就能推算出每天的订单量 )

5)每次获取 ID 都要访问一次数据库(增加了对数据库的压力,获取速度也慢)

数据库号段模式

1)ID 有序递增

2)存储消耗空间小

1)存在数据库单点问题(可以使用数据库集群解决,不过增加了复杂度)

2)ID 没有具体业务含义

3)安全问题(比如根据订单 ID 的递增规律就能推算出每天的订单量)

Redis自增 1)性能不错并且生成的 ID 是有序递增的 1)和数据库主键自增方案的缺点类似
算法

UUID

1)生成速度比较快

2)简单易用

1)存储消耗空间大(32 个字符串,128 位) 

2)不安全(基于 MAC 地址生成 UUID 的算法会造成 MAC 地址泄露)

3)无序(非自增)

4)没有具体业务含义

5)需要解决重复 ID 问题(当机器时间不对的情况下,可能导致会产生重复 ID)

Snowflake

1)生成速度比较快

2)生成的 ID 有序递增

3)比较灵活(可以对 Snowflake 算法进行简单的改造比如加入业务 ID)

1)需要解决重复 ID 问题(依赖时间,当机器时间不对的情况下,可能导致会产生重复 ID)

3. 开源框架

3.1 UidGenerator(百度)

基于 Snowflake 的唯一 ID 生成器,并对其进行了改进。其中1bit为标识位,28bit代表时间戳,22bit标识一台机器,13bit则用来标识每个id。

详见:UidGenerator

3.2 Leaf(美团)

提供了 号段模式 和 Snowflake 这两种模式来生成分布式 ID。

Leaf 对原有的号段模式进行改进,比如它这里增加了双号段避免获取 DB 在获取号段的时候阻塞请求获取 ID 的线程。简单来说,就是我一个号段还没用完之前,我自己就主动提前去获取下一个号段。

详见:Leaf——美团点评分布式ID生成系统

3.3 Tinyid(滴滴)

基于数据库号段模式的唯一 ID 生成器。

相比于基于数据库号段模式的简单架构方案,Tinyid 方案主要做了下面这些优化:

  • 双号段缓存 :为了避免在获取新号段的情况下,程序获取唯一 ID 的速度比较慢。 Tinyid 中的号段在用到一定程度的时候,就会去异步加载下一个号段,保证内存中始终有可用号段。
  • 增加多 db 支持 :支持多个 DB,并且,每个 DB 都能生成唯一 ID,提高了可用性。
  • 增加 tinyid-client :纯本地操作,无 HTTP 请求消耗,性能和可用性都有很大提升。

详见:Tinyid原理介绍

Logo

更多推荐