掘金是如何生成文章ID的?SnowFlake揭秘
2023-11-09 15:23:42
数据库中的主键:为你的数据赋予身份
数据库是存储和管理数据的关键工具,而主键是确保数据完整性和可靠性的核心要素。本文将深入探讨数据库主键的设计,并特别关注 UUID 和 Snowflake 雪花算法在掘金文章 ID 生成中的应用。
主键的重要性
主键是数据库表中唯一标识每一行的字段。选择一个有效的为主键至关重要,它直接影响数据库的性能和可靠性。常见的类型包括:
- 整数自增主键: 简单易用,通过递增的整数为每一行分配唯一标识符。
- UUID: 通用唯一标识符,由 32 个十六进制数字组成,全球范围内唯一。
- Snowflake 雪花算法: 分布式主键生成算法,生成具有全局唯一性的 ID。
UUID 和 Snowflake 雪花算法的较量
UUID 和 Snowflake 雪花算法都是生成唯一 ID 的常用方法,但两者之间存在差异:
- UUID: 高度唯一性,但较长且无序。
- Snowflake 雪花算法: 唯一性高,有序,且相对较短。
掘金文章 ID 的生成机制
掘金采用 Snowflake 雪花算法来生成文章 ID。这种算法由 Twitter 开发,利用时间戳、机器 ID 和序列号生成全局唯一且有序的 ID。掘金使用这些 ID 作为文章的主键,确保文章的唯一性和按时间顺序的排列。
Snowflake 雪花算法的优势
- 唯一性: 全局唯一,即使在分布式系统中也是如此。
- 有序性: 按时间顺序生成,适合存储时间序列数据。
- 短小: 通常只有 64 位,存储空间占用小。
- 易于实现: 实现相对简单,易于集成。
Snowflake 雪花算法的不足
- 存储空间: 较长的 ID 可能会占用更多的存储空间。
- 计算资源: 生成 ID 需要额外的计算资源,可能影响系统性能。
代码示例:使用 Java 生成 Snowflake ID
import java.util.UUID;
public class SnowflakeIdGenerator {
private static final long EPOCH = 1420070400000L;
private static final long DATA_CENTER_ID_BITS = 5L;
private static final long WORKER_ID_BITS = 5L;
private static final long SEQUENCE_BITS = 12L;
private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS;
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS + DATA_CENTER_ID_BITS;
private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + DATA_CENTER_ID_BITS + WORKER_ID_BITS;
private static final long DATA_CENTER_ID_MAX = ~(-1L << DATA_CENTER_ID_BITS);
private static final long WORKER_ID_MAX = ~(-1L << WORKER_ID_BITS);
private static final long SEQUENCE_MAX = ~(-1L << SEQUENCE_BITS);
private final long dataCenterId;
private final long workerId;
private long sequence;
private long lastTimestamp;
public SnowflakeIdGenerator(long dataCenterId, long workerId) {
if (dataCenterId > DATA_CENTER_ID_MAX || dataCenterId < 0) {
throw new IllegalArgumentException("dataCenterId must be between 0 and " + DATA_CENTER_ID_MAX);
}
if (workerId > WORKER_ID_MAX || workerId < 0) {
throw new IllegalArgumentException("workerId must be between 0 and " + WORKER_ID_MAX);
}
this.dataCenterId = dataCenterId;
this.workerId = workerId;
this.sequence = 0L;
this.lastTimestamp = -1L;
}
public synchronized long generateId() {
long timestamp = timeGen();
// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟被调整过,故抛出异常
if (timestamp < lastTimestamp) {
throw new IllegalStateException("Clock moved backwards.");
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & SEQUENCE_MAX;
// 序列号溢出
if (sequence == 0L) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
// 如果时间戳改变,则将序列号重置为0
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - EPOCH) << TIMESTAMP_LEFT_SHIFT) | (dataCenterId << DATA_CENTER_ID_SHIFT) | (workerId << WORKER_ID_SHIFT) | sequence;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
public static void main(String[] args) {
SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1L, 1L);
for (int i = 0; i < 10; i++) {
System.out.println(idGenerator.generateId());
}
}
}
结论
Snowflake 雪花算法在掘金文章 ID 的生成中扮演着至关重要的角色。它提供了高唯一性、有序性和相对较短的 ID,确保文章数据的可靠性和可管理性。随着数据库技术的不断发展,主键的选择和生成算法将继续发挥关键作用,为数据管理提供高效和可靠的基础。
常见问题解答
- UUID 和 Snowflake 雪花算法哪个更好?
在唯一性、有序性和存储空间等方面,Snowflake 雪花算法略胜一筹。
- 主键在数据库中的作用是什么?
主键唯一标识每一行数据,确保数据的完整性和可管理性。
- Snowflake 雪花算法是如何工作的?
它将 ID 划分为时间戳、机器 ID 和序列号,并通过组合它们来生成唯一 ID。
- 掘金为什么选择 Snowflake 雪花算法?
它提供了高唯一性、有序性和较短的 ID,满足掘金文章管理的需求。
- 如何使用 Snowflake 雪花算法生成 ID?
您可以使用提供的 Java 代码示例,或使用其他可用的实现。