冷饮店怎么做网站,网站做的一样算不算侵权,dw做的网站怎么全屏,怎么管理好自己的网站雪花算法#xff08;Snowflake Algorithm#xff09;是一种分布式唯一ID生成算法#xff0c;主要用于生成全球唯一的ID#xff0c;广泛应用于分布式系统中#xff0c;例如在数据库中作为主键。这个算法最初由Twitter提出#xff0c;并且被广泛使用在很多大规模系统中。有…雪花算法Snowflake Algorithm是一种分布式唯一ID生成算法主要用于生成全球唯一的ID广泛应用于分布式系统中例如在数据库中作为主键。这个算法最初由Twitter提出并且被广泛使用在很多大规模系统中。有以下特性
唯一性 确保生成的每一个ID都是全球唯一的避免冲突。
时间有序性 根据生成ID的时间戳使得ID按时间顺序排列方便进行时间排序和处理。
高效性 在高并发环境下能够快速生成ID通常在每毫秒内能够生成多个ID。 雪花算法的核心思想是将ID分解成几个部分以确保生成的ID具有唯一性同时又能保持一定的顺序性。它的ID结构一般包括以下几个部分
时间戳Timestamp 用于表示当前时间的毫秒数。通常时间戳占用最前面的一部分位数这样可以保证ID在时间上有序。
数据中心IDData Center ID 用于标识不同的数据中心确保在不同的数据中心生成的ID不会冲突。
工作机器IDWorker ID 用于标识同一数据中心下的不同工作机器确保同一数据中心内的不同机器生成的ID也不会冲突。
序列号Sequence Number 用于在同一毫秒内生成多个ID以保证同一时间戳下生成的ID仍然唯一。 雪花算法通常生成的ID长度是64位具体结构可能有所不同但一个常见的结构是
1位符号位通常固定为0
41位时间戳表示毫秒数一般支持约69年的时间范围
10位数据中心ID和工作机器ID分为5位数据中心ID和5位工作机器ID支持最多1024个数据中心每个数据中心支持最多1024台机器
12位序列号支持每毫秒生成4096个不同的ID
这种设计可以保证生成的ID是全局唯一的同时还能保持一定的顺序性适用于高并发的分布式系统。
工作原理
生成ID时算法会获取当前时间戳。
结合数据中心ID、工作机器ID以及序列号生成唯一ID。
如果在同一毫秒内生成多个ID算法会增加序列号以确保唯一性。
在时间戳变化时算法会重置序列号并更新ID的时间戳部分。
优点有
全局唯一性能够在分布式系统中确保生成的ID全局唯一。
趋势递增性生成的ID基本呈趋势递增有利于数据库性能优化。
灵活性可以根据业务特性灵活分配bit位。
高性能不依赖数据库等第三方系统以服务方式部署生成ID的性能高。
缺陷有
时钟回退问题雪花算法依赖于系统时间戳来生成唯一 ID。如果系统时间被设置回过去可能会导致生成重复的 ID 或者抛出异常。这是使用雪花算法时需要特别注意的问题因为时钟回退会直接影响到 ID 的唯一性和生成稳定性。
时间戳依赖雪花算法的 ID 生成是基于系统时间戳的。如果系统时间出现问题如时钟漂移或系统时间错误则会影响 ID 的生成。这使得系统时间的准确性和稳定性变得至关重要。
数据中心 ID 和工作机器 ID 的管理需要合理分配和管理数据中心 ID 和工作机器 ID以避免冲突。在大规模分布式系统中如何分配和协调这些 ID 是一个挑战错误的配置可能导致 ID 冲突或生成不一致。
高并发处理复杂性在高并发场景下雪花算法通过序列号来处理生成的 ID但在极高负载情况下仍然需要精细管理性能和同步问题。高并发可能导致性能瓶颈或增加实现的复杂性。
代码实现
public class SnowflakeIdGenerator {// 起始时间戳 (2020-01-01 00:00:00)private static final long START_TIMESTAMP 1577836800000L;// 工作机器 ID 位数private static final long WORKER_ID_BITS 5L;// 数据中心 ID 位数private static final long DATA_CENTER_ID_BITS 5L;// 序列号位数private static final long SEQUENCE_BITS 12L;// 工作机器 ID 最大值private static final long MAX_WORKER_ID ~(-1L WORKER_ID_BITS);// 数据中心 ID 最大值private static final long MAX_DATA_CENTER_ID ~(-1L DATA_CENTER_ID_BITS);// 序列号最大值private static final long SEQUENCE_MASK ~(-1L SEQUENCE_BITS);// 工作机器 ID 和数据中心 IDprivate final long workerId;private final long dataCenterId;// 序列号和上次时间戳private long sequence 0L;private long lastTimestamp -1L;/*** 构造函数初始化工作机器 ID 和数据中心 ID。* * param workerId 工作机器 ID* param dataCenterId 数据中心 ID* throws IllegalArgumentException 如果 workerId 或 dataCenterId 超出范围*/public SnowflakeIdGenerator(long workerId, long dataCenterId) {if (workerId MAX_WORKER_ID || workerId 0) {throw new IllegalArgumentException(Worker ID out of range);}if (dataCenterId MAX_DATA_CENTER_ID || dataCenterId 0) {throw new IllegalArgumentException(Data Center ID out of range);}this.workerId workerId;this.dataCenterId dataCenterId;}/*** 生成下一个唯一的 ID。* * return 生成的 ID*/public synchronized long nextId() {long timestamp currentTimestamp();// 检查时钟是否回退if (timestamp lastTimestamp) {throw new RuntimeException(Clock moved backwards. Refusing to generate id);}// 当前时间戳与上次时间戳相同处理序列号溢出if (timestamp lastTimestamp) {sequence (sequence 1) SEQUENCE_MASK;if (sequence 0) {timestamp waitNextMillis(lastTimestamp);}} else {// 当前时间戳不同重置序列号sequence 0L;}lastTimestamp timestamp;// 生成唯一 IDreturn ((timestamp - START_TIMESTAMP) (WORKER_ID_BITS DATA_CENTER_ID_BITS SEQUENCE_BITS)) |(dataCenterId (WORKER_ID_BITS SEQUENCE_BITS)) |(workerId SEQUENCE_BITS) |sequence;}/*** 等待直到下一个毫秒。* * param lastTimestamp 上次生成 ID 的时间戳* return 当前时间戳*/private long waitNextMillis(long lastTimestamp) {long timestamp currentTimestamp();while (timestamp lastTimestamp) {timestamp currentTimestamp();}return timestamp;}/*** 获取当前时间戳。* * return 当前时间戳毫秒*/private long currentTimestamp() {return System.currentTimeMillis();}/*** 测试生成 ID。* * param args 命令行参数*/public static void main(String[] args) {SnowflakeIdGenerator idGenerator new SnowflakeIdGenerator(1, 1);for (int i 0; i 10; i) {System.out.println(idGenerator.nextId());}}
}