18.9.3 分布式ID生成方案对比
1. 分布式ID生成方案概述
1.1 分布式ID基本要求
public class DistributedIdPrinciple {
/*
* 分布式ID基本要求:
*
* 1. 全局唯一性
* - 在分布式环境下保证ID的唯一性
*
* 2. 高性能
* - 生成速度快,支持高并发
*
* 3. 高可用
* - 服务高可用,不能成为单点故障
*
* 4. 趋势递增
* - 大致按时间递增,便于数据库索引
*
* 5. 信息安全
* - 不能暴露业务信息,防止被猜测
*
* 常见方案:
* - UUID
* - 数据库自增ID
* - Redis原子操作
* - 雪花算法(Snowflake)
* - 美团Leaf
* - 百度UidGenerator
*/
public void demonstrateIdGenerationSchemes() {
System.out.println("=== 分布式ID生成方案演示 ===");
demonstrateUUID();
demonstrateDatabaseIncrement();
demonstrateRedisIncrement();
demonstrateSnowflake();
}
private void demonstrateUUID() {
System.out.println("--- UUID方案演示 ---");
UUIDGenerator uuidGenerator = new UUIDGenerator();
System.out.println("1. 生成UUID:");
for (int i = 0; i < 5; i++) {
String uuid = uuidGenerator.generateId();
System.out.println(" " + uuid);
}
System.out.println("\n2. UUID特点:");
System.out.println(" 优点: 简单易用,本地生成,性能高");
System.out.println(" 缺点: 长度较长,无序,不适合数据库主键");
System.out.println();
}
private void demonstrateDatabaseIncrement() {
System.out.println("--- 数据库自增ID演示 ---");
DatabaseIdGenerator dbGenerator = new DatabaseIdGenerator();
System.out.println("1. 生成数据库自增ID:");
for (int i = 0; i < 5; i++) {
long id = dbGenerator.generateId();
System.out.println(" " + id);
}
System.out.println("\n2. 数据库自增ID特点:");
System.out.println(" 优点: 简单,有序递增,适合数据库");
System.out.println(" 缺点: 单点故障,性能瓶颈,扩展困难");
System.out.println();
}
private void demonstrateRedisIncrement() {
System.out.println("--- Redis原子操作演示 ---");
RedisIdGenerator redisGenerator = new RedisIdGenerator();
System.out.println("1. 生成Redis自增ID:");
for (int i = 0; i < 5; i++) {
long id = redisGenerator.generateId();
System.out.println(" " + id);
}
System.out.println("\n2. Redis自增ID特点:");
System.out.println(" 优点: 性能高,有序递增,支持集群");
System.out.println(" 缺点: 依赖Redis,可能丢失数据");
System.out.println();
}
private void demonstrateSnowflake() {
System.out.println("--- 雪花算法演示 ---");
SnowflakeIdGenerator snowflake = new SnowflakeIdGenerator(1, 1);
System.out.println("1. 生成Snowflake ID:");
for (int i = 0; i < 5; i++) {
long id = snowflake.generateId();
System.out.println(" " + id + " (二进制: " + Long.toBinaryString(id) + ")");
}
System.out.println("\n2. Snowflake特点:");
System.out.println(" 优点: 高性能,趋势递增,包含时间信息");
System.out.println(" 缺点: 依赖系统时钟,时钟回拨问题");
System.out.println();
}
}
// UUID生成器
class UUIDGenerator {
public String generateId() {
return java.util.UUID.randomUUID().toString().replace("-", "");
}
}
// 数据库自增ID生成器
class DatabaseIdGenerator {
private long currentId = 1000;
public synchronized long generateId() {
// 模拟数据库自增操作
try {
Thread.sleep(1); // 模拟数据库访问延迟
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return ++currentId;
}
}
// Redis自增ID生成器
class RedisIdGenerator {
private long currentId = 10000;
public synchronized long generateId() {
// 模拟Redis INCR操作
return ++currentId;
}
}
// 雪花算法ID生成器
class SnowflakeIdGenerator {
// 起始时间戳 (2020-01-01)
private final long START_TIMESTAMP = 1577836800000L;
// 各部分位数
private final long SEQUENCE_BITS = 12;
private final long MACHINE_BITS = 5;
private final long DATACENTER_BITS = 5;
// 最大值
private final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1;
private final long MAX_MACHINE_NUM = (1L << MACHINE_BITS) - 1;
private final long MAX_DATACENTER_NUM = (1L << DATACENTER_BITS) - 1;
// 位移
private final long MACHINE_LEFT = SEQUENCE_BITS;
private final long DATACENTER_LEFT = SEQUENCE_BITS + MACHINE_BITS;
private final long TIMESTAMP_LEFT = DATACENTER_LEFT + DATACENTER_BITS;
private long datacenterId;
private long machineId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public SnowflakeIdGenerator(long datacenterId, long machineId) {
if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
}
if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
}
this.datacenterId = datacenterId;
this.machineId = machineId;
}
public synchronized long generateId() {
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
Java面试圣经 文章被收录于专栏
Java面试圣经,带你练透java圣经

