分布式架构会波及到分布式全局惟一 ID 的生成,明天我就来详解分布式全局惟一 ID,以及分布式全局惟一 ID 的实现计划 @mikechen
什么是分布式系统惟一 ID
在简单分布式系统中,往往须要对大量的数据和音讯进行惟一标识。
如在金融、电商、领取、等产品的零碎中,数据日渐增长,对数据分库分表后须要有一个惟一 ID 来标识一条数据或音讯,数据库的自增 ID 显然不能满足需要,此时一个可能生成全局惟一 ID 的零碎是十分必要的。
分布式系统惟一 ID 的特点
- 全局唯一性:不能呈现反复的 ID 号,既然是惟一标识,这是最根本的要求。
- 趋势递增:在 MySQL InnoDB 引擎中应用的是汇集索引,因为少数 RDBMS 应用 B -tree 的数据结构来存储索引数据,在主键的抉择下面咱们应该尽量应用有序的主键保障写入性能。
- 枯燥递增:保障下一个 ID 肯定大于上一个 ID,例如事务版本号、IM 增量音讯、排序等非凡需要。
- 信息安全:如果 ID 是间断的,歹意用户的扒取工作就非常容易做了,间接依照程序下载指定 URL 即可;如果是订单号就更危险了,竞对能够间接晓得咱们一天的单量。所以在一些利用场景下,会须要 ID 无规则、不规则。
同时除了对 ID 号码本身的要求,业务还对 ID 号生成零碎的可用性要求极高,设想一下,如果 ID 生成零碎瘫痪,这就会带来一场劫难。
由此总结下一个 ID 生成零碎应该做到如下几点:
- 均匀提早和 TP999 提早都要尽可能低;
- 可用性 5 个 9;
- 高 QPS
\
分布式系统惟一 ID 的实现计划
1.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 长处:
- 性能十分高:本地生成,没有网络耗费。
UUID 毛病:
- 不易于存储:UUID 太长,16 字节 128 位,通常以 36 长度的字符串示意,很多场景不实用;
- 信息不平安:基于 MAC 地址生成 UUID 的算法可能会造成 MAC 地址泄露,这个破绽曾被用于寻找梅丽莎病毒的制作者地位;
- ID 作为主键时在特定的环境会存在一些问题,比方做 DB 主键的场景下,UUID 就十分不实用。
\
2. 数据库生成 ID
以 MySQL 举例,利用给字段设置 auto_increment_increment 和 auto_increment_offset 来保障 ID 自增,每次业务应用下列 SQL 读写 MySQL 失去 ID 号。
数据库生成 ID 长处:
- 非常简单,利用现有数据库系统的性能实现,老本小,有 DBA 业余保护。
- ID 号枯燥自增,能够实现一些对 ID 有特殊要求的业务。
数据库生成 ID 毛病:
- 强依赖 DB,当 DB 异样时整个零碎不可用,属于致命问题。配置主从复制能够尽可能的减少可用性,然而数据一致性在非凡状况下难以保障。主从切换时的不统一可能会导致反复发号。
- ID 发号性能瓶颈限度在单台 MySQL 的读写性能。
\
3.Redis 生成 ID
当应用数据库来生成 ID 性能不够要求的时候,咱们能够尝试应用 Redis 来生成 ID。
这次要依赖于 Redis 是单线程的,所以也能够用生成全局惟一的 ID。能够用 Redis 的原子操作 INCR 和 INCRBY 来实现。
比拟适宜应用 Redis 来生成每天从 0 开始的流水号。比方订单号 = 日期 + 当日自增长号。能够每天在 Redis 中生成一个 Key,应用 INCR 进行累加。
Redis 生成 ID 长处:
1)不依赖于数据库,灵便不便,且性能优于数据库。
2)数字 ID 人造排序,对分页或者须要排序的后果很有帮忙。
\
Redis 生成 ID 毛病:
1)如果零碎中没有 Redis,还须要引入新的组件,减少零碎复杂度。
2)须要编码和配置的工作量比拟大。
4. 利用 zookeeper 生成惟一 ID
zookeeper 次要通过其 znode 数据版本来生成序列号,能够生成 32 位和 64 位的数据版本号,客户端能够应用这个版本号来作为惟一的序列号。
很少会应用 zookeeper 来生成惟一 ID。次要是因为须要依赖 zookeeper,并且是多步调用 API,如果在竞争较大的状况下,须要思考应用分布式锁。因而,性能在高并发的分布式环境下,也不甚现实。
5.snowflake 雪花算法生成 ID
这种计划大抵来说是一种以划分命名空间(UUID 也算,因为比拟常见,所以独自剖析)来生成 ID 的一种算法,这种计划把 64-bit 别离划分成多段,离开来标示机器、工夫等,比方在 snowflake 中的 64-bit 别离示意如下图(图片来自网络)所示:
41-bit 的工夫能够示意(1L<<41)/(1000L360024*365)=69 年的工夫,10-bit 机器能够别离示意 1024 台机器。如果咱们对 IDC 划分有需要,还能够将 10-bit 分 5 -bit 给 IDC,分 5 -bit 给工作机器。这样就能够示意 32 个 IDC,每个 IDC 下能够有 32 台机器,能够依据本身需要定义。12 个自增序列号能够示意 2^12 个 ID,实践上 snowflake 计划的 QPS 约为 409.6w/s,这种调配形式能够保障在任何一个 IDC 的任何一台机器在任意毫秒内生成的 ID 都是不同的。
雪花算法 ID 长处:
- 毫秒数在高位,自增序列在低位,整个 ID 都是趋势递增的。
- 不依赖数据库等第三方零碎,以服务的形式部署,稳定性更高,生成 ID 的性能也是十分高的。
- 能够依据本身业务个性调配 bit 位,非常灵活。
雪花算法 ID 毛病:
- 强依赖机器时钟,如果机器上时钟回拨,会导致发号反复或者服务会处于不可用状态。
以上
作者简介
陈睿 |mikechen,10 年 + 大厂架构教训,《BAT 架构技术 500 期》系列文章作者,专一于互联网架构技术。
浏览 mikechen 的互联网架构更多技术文章合集
Java 并发 |JVM|MySQL|Spring|Redis| 分布式 | 高并发
关注「mikechen 的互联网架构」公众号,回复 【架构】 支付《Java 进阶架构思维导图 &Java 进阶架构文章合集》