20211101-如何设计唯一性id

参考文章 https://zhuanlan.zhihu.com/p/154480290

文章参考脑图

什么是唯一性id

定义

在业务场景中,标识唯一性。主要为了解决业务重复性问题。

常见业务场景:
分库分表数据库表主键
请求链路id
...

特点

唯一性id主要要包含如下几个特点:
1,全局唯一性:不能出现重复的 ID 号,既然是唯一标识,这是最基本的要求;
2,趋势递增:在 MySQL InnoDB 引擎中使用的是聚集索引,由于多数 RDBMS 使用 B-tree 的数据结构来存储索引数据,
在主键的选择上面我们应该尽量使用有序的主键保证写入性能;
3,单调递增:保证下一个 ID 一定大于上一个 ID,例如事务版本号、IM 增量消息、排序等特殊需求;
4,信息安全:如果 ID 是连续的,恶意用户的爬取工作就非常容易做了,直接按照顺序下载指定 URL 即可;
如果是订单号就更危险了,竞争对手可以直接知道我们一天的单量。
所以在一些应用场景下,会需要 ID 无规则、不规则。
综合下来,主要包含如下几个特点:

  • 全局唯一性
  • 是否支持有序和递增。
  • 是否支持高QPS、高可用性和低延迟

常见的技术实现和选型

目前常见的技术实现主要有以下几个数据点:

  • UUID
  • 基于雪花算法实现
  • 自增长id

UUID

UUID(Universally Unique Identifier)的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12的36个字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前为止业界一共有5种方式生成UUID,详情见IETF发布的UUID规范 A Universally Unique IDentifier (UUID) URN Namespace。

优点:

性能非常高:本地生成,没有网络消耗。
缺点:

不易于存储:UUID太长,16字节128位,通常以36长度的字符串表示,很多场景不适用。
信息不安全:基于MAC地址生成UUID的算法可能会造成MAC地址泄露,这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。

ID作为主键时在特定的环境会存在一些问题,比如做DB主键的场景下,UUID就非常不适用:

① MySQL官方有明确的建议主键要尽量越短越好[4],36个字符长度的UUID不符合要求。

All indexes other than the clustered index are known as secondary indexes. In InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index. InnoDB uses this primary key value to search for the row in the clustered index.*** If the primary key is long, the secondary indexes use more space, so it is advantageous to have a short primary key***.

② 对MySQL索引不利:如果作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能。

基于雪花算法的实现

这种方案大致来说是一种以划分命名空间(UUID也算,由于比较常见,所以单独分析)来生成ID的一种算法,这种方案把64-bit分别划分成多段,分开来标示机器、时间等,比如在snowflake中的64-bit分别表示如下图(图片来自网络)所示

关键词:

一共64位
分为3部分,41位时间戳,10位机器id,12位自增长。

特点

优点:

毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。
不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。
可以根据自身业务特性分配bit位,非常灵活。

缺点:

强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。

自己增长的id

常见的开源解决方案

自己实现

原文地址:https://www.cnblogs.com/original123/p/15492324.html