在开发分布式系统或设计多人在线服务时,经常要给每个用户、设备或操作打上唯一标记。如果标识重复,轻则数据错乱,重则系统崩溃。比如你家的智能门锁和邻居的用了同一个识别码,刷谁的卡都能开门,这显然不行。
为什么普通ID容易“撞车”?
很多人图省事用时间戳加随机数拼个ID,看似没问题,但在高并发场景下隐患很大。两个服务器在同一毫秒生成了相同的随机数,ID就重复了。这种“碰撞”在小项目里可能几年碰不上一次,可一旦上了百万级用户,每天都能撞出几回。
真正低碰撞率的做法
现在主流方案是结合多种维度生成ID。比如雪花算法(Snowflake),它把时间戳、机器ID、序列号打包成一个64位整数。这样即使两台机器同时请求,只要机器ID不同,生成的ID也不会重复。
public class SnowflakeId {
private long workerId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards!");
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & 0xFFF;
if (sequence == 0) {
timestamp = waitNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - 1288834974657L) << 22) |
(workerId << 12) |
sequence;
}
}
上面这段Java代码就是典型的实现。时间戳部分精确到毫秒,机器ID最多支持1024台节点,每毫秒能生成4096个不重复ID,理论碰撞概率几乎为零。
推荐几个现成工具
不想自己写?直接用现成库更省心。Node.js 下可以用 ulid,它基于时间排序,字符串长度比UUID短,还支持按时间检索。Python 推荐 uuid7,这是新出的标准,结合了时间戳和随机熵,既唯一又可读。
如果你做的是物联网项目,设备多且离线频繁,可以试试MongoDB的ObjectId。它前4字节是时间戳,中间3字节是机器标识,后2字节进程ID加计数器,本地就能生成,不需要联网协调。
选哪种方案,关键看你的系统规模和部署方式。小项目用UUID也能凑合,但想长期稳定运行,还是得上低碰撞率的生成策略。