关于java:分布式ID详解5种分布式ID生成方案

29次阅读

共计 2490 个字符,预计需要花费 7 分钟才能阅读完成。

分布式架构会波及到分布式全局惟一 ID 的生成,明天我就来详解分布式全局惟一 ID,以及分布式全局惟一 ID 的实现计划 @mikechen

什么是分布式系统惟一 ID

在简单分布式系统中,往往须要对大量的数据和音讯进行惟一标识。

如在金融、电商、领取、等产品的零碎中,数据日渐增长,对数据分库分表后须要有一个惟一 ID 来标识一条数据或音讯,数据库的自增 ID 显然不能满足需要,此时一个可能生成全局惟一 ID 的零碎是十分必要的。

分布式系统惟一 ID 的特点

  1. 全局唯一性:不能呈现反复的 ID 号,既然是惟一标识,这是最根本的要求。
  2. 趋势递增:在 MySQL InnoDB 引擎中应用的是汇集索引,因为少数 RDBMS 应用 B -tree 的数据结构来存储索引数据,在主键的抉择下面咱们应该尽量应用有序的主键保障写入性能。
  3. 枯燥递增:保障下一个 ID 肯定大于上一个 ID,例如事务版本号、IM 增量音讯、排序等非凡需要。
  4. 信息安全:如果 ID 是间断的,歹意用户的扒取工作就非常容易做了,间接依照程序下载指定 URL 即可;如果是订单号就更危险了,竞对能够间接晓得咱们一天的单量。所以在一些利用场景下,会须要 ID 无规则、不规则。

同时除了对 ID 号码本身的要求,业务还对 ID 号生成零碎的可用性要求极高,设想一下,如果 ID 生成零碎瘫痪,这就会带来一场劫难。

由此总结下一个 ID 生成零碎应该做到如下几点:

  1. 均匀提早和 TP999 提早都要尽可能低;
  2. 可用性 5 个 9;
  3. 高 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 进阶架构文章合集》

正文完
 0