毫秒并发 ID (MCID) 生成方案
1. 引言
在数字时代,唯一标识符的生成对于维护数据完整性、支持分布式系统以及确保准确的事务处理至关重要。毫秒并发 ID (MCID) 生成方案是一种高精度、可扩展的解决方案,旨在为需要毫秒级精度和高并发支持的实时系统生成唯一标识符。本文件概述了 MCID 方案的设计、实现及标准化建议,并特别强调了其对前端浏览器的支持能力。
2. 问题描述
随着现代应用程序和分布式系统的扩展,独特且一致的标识符生成方案变得日益重要。时间戳精度、高并发处理和确保分布式环境中的唯一性等挑战,迫切需要一种强大的 ID 生成策略。
传统的雪花 ID(Snowflake ID)生成方案使用 64 位二进制整数来生成唯一 ID。然而,由于前端浏览器的Number
类型基于 IEEE 754 标准,只能精确表示到 53 位二进制位的整数。这导致了雪花 ID 通常需要转换为字符串格式才能在前端安全使用,增加了数据传输和处理的开销。MCID 方案的设计目的就是为了解决这个问题,提供一种不需要转换为字符串即可在前端安全使用的 ID 生成机制。
3. 目标
MCID 方案的主要目标包括:
- 精度:利用毫秒级时间戳确保事件的及时排序。
- 并发性:支持在同一毫秒内的高并发 ID 生成。
- 可扩展性:提供一种在分布式系统中可扩展的机制,同时保持 ID 的唯一性。
- 效率:生成紧凑的数字 ID,便于存储、索引和处理。
- 前端兼容性:确保生成的 ID 能够在前端浏览器中安全地作为
Number
类型使用,避免精度损失。
4. 设计概述
MCID 方案通过结合三个组成部分生成唯一标识符:
- 时间戳部分:主要部分,表示自 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)以来的当前毫秒数。
- 机器或进程标识符:次要部分,用于区分不同机器或进程生成的 ID,确保分布式环境中的唯一性。
- 序列号:在同一毫秒内生成多个 ID 时递增的计数器,处理高并发场景。
4.1 MCID 的结构
MCID 是一个不超过 53 位二进制的整数,由以下部分组成:
- 时间戳(41 位):表示自 Unix 纪元以来的毫秒数。
- 机器/进程 ID(8 位):用于区分生成 ID 的机器或进程,确保分布式环境中的唯一性。
- 序列号(4 位):在同一毫秒内递增的计数器,支持每毫秒最多 16 个唯一 ID。
4.2 位分配
- 41 位 用于时间戳:覆盖大约 69 年,这对于大多数应用场景来说是足够的。
- 8 位 用于机器/进程 ID:支持多达 256 台机器或进程的分布式环境。
- 4 位 用于序列号:支持每毫秒最多 16 个唯一 ID。
4.3 前端浏览器支持
MCID 生成的 ID 严格控制在 53 位二进制以内,这使得它可以安全地在前端浏览器中作为 Number
类型使用,而无需转换为字符串。这种设计有效避免了雪花 ID 在前端处理时需要转换为字符串的额外开销,从而提高了效率并简化了数据传输。
4.4 MCID 生成算法
- 时间戳部分:使用高精度系统时钟获取当前毫秒时间戳。
- 机器/进程 ID:使用预定义的机器或进程的唯一标识符。
- 序列号:如果在同一毫秒内生成多个 ID,则递增序列号。如果序列号超出最大值(15),则等待下一毫秒。
4.5 示例实现
5. 性能考虑
- 时间精度:41 位的时间戳提供了毫秒级的精度,支持事件排序,对于时间敏感的应用至关重要。
- 并发性:4 位的序列号确保每毫秒在单台机器或进程上可以生成多达 16 个唯一 ID,相比之前的方案大幅提升了并发处理能力,适合高并发环境。
- 可扩展性:8 位的机器/进程 ID 支持多达 256 个分布式节点,每个节点能够独立生成 ID 而不会发生冲突。
- 前端兼容性:生成的 ID 在前端浏览器中可以安全地作为
Number
类型使用,确保跨平台操作的一致性。
6. 适用场景
MCID 方案适用于广泛的应用场景,包括但不限于:
- 分布式系统:需要在多个节点或进程之间生成唯一标识符。
- 事务处理:确保金融系统中的唯一事务 ID。
- 事件日志记录:以毫秒精度捕获和排序事件。
- 数据同步:在需要跨分布式数据库生成全球唯一且有序的标识符的系统中。
- Web 应用程序:需要在前端浏览器中处理唯一 ID,并确保其在
Number
类型下的精度和一致性。
7. 结论
毫秒并发 ID (MCID) 生成方案是一种强大、可扩展且高效的解决方案,能够在现代分布式系统中生成唯一标识符。通过利用毫秒级精度、支持高并发、确保全球唯一性,MCID 满足了当今高性能、实时应用的需求。其在前端浏览器中的良好支持确保了跨平台的一致性和安全性。同时,MCID 方案的设计避免了雪花 ID 在前端必须转换为字符串的缺陷,使其成为更加高效的替代方案。采用该方案将标准化唯一 ID 的生成,提高技术生态系统中的互操作性和可靠性。
8. Java 实现
package com.litongjava.open.chat.mcid;
public class McIdGenerator {
private final int machineId;
private int sequence = 0;
private long lastTimestamp = -1L;
public McIdGenerator(int machineId) {
if (machineId < 0 || machineId > 255) { // 8位机器/进程ID限制
throw new IllegalArgumentException("Machine ID must be between 0 and 255");
}
this.machineId = machineId;
}
public synchronized long generateId() {
long timestamp = System.currentTimeMillis();
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & 15; // 4位序列号
if (sequence == 0) {
while (System.currentTimeMillis() <= timestamp) {
// 等待下一毫秒
}
timestamp = System.currentTimeMillis();
}
} else {
sequence = 0;
}
lastTimestamp = timestamp;
// 41位时间戳 | 8位机器/进程ID | 4位序列号
return ((timestamp & 0x1FFFFFFFFFFL) << 12) | (machineId << 4) | sequence;
}
public static void main(String[] args) {
McIdGenerator generator = new McIdGenerator(1); // 机器ID = 1
for(int i=0;i<10000;i++) {
long id = generator.generateId();
System.out.println(id); // 输出生成的唯一ID
}
}
}
tio-utils
import com.litongjava.tio.utils.mcid.McIdUtils;
long id = McIdUtils.id();