当前位置: 首页 > news >正文

深入解析:【分布式利器:分布式ID】6、中间件方案:Redis/ZooKeeper分布式ID实现

# 第6篇:中间件方案:Redis/ZooKeeper分布式ID实现

系列导读

上一篇的UUID方案适合无依赖场景,但如果你的系统已经部署了Redis(缓存)或ZooKeeper(服务注册中心),没必要再引入雪花算法、号段模式等新方案——直接复用现有中间件就能实现分布式ID,减少系统依赖和维护成本。
本文详解Redis和ZooKeeper的分布式ID实现方案,附实战代码,帮你快速复用现有组件落地。

一、适用场景

  • 系统已部署Redis/ZooKeeper(避免重复引入中间件);
  • 中低并发场景(Redis:QPS万级+;ZooKeeper:QPS千级);
  • 需ID有序(支持排序、分页);
  • 代表业务:
    • Redis:电商优惠券ID、活动ID、中小型系统订单ID;
    • ZooKeeper:配置中心标识、分布式锁关联ID、低并发业务ID。

二、方案1:Redis分布式ID(基于INCR原子操作)

1. 核心原理

Redis的INCR/INCRBY命令是原子操作,支持跨客户端递增,天然适合生成自增ID:

2. 进阶优化:避免ID重置+增加业务前缀

  • 问题:Redis重启后,键值会丢失,ID会从1重新开始,导致重复;
  • 解决方案:
    1. Redis开启持久化(RDB+AOF),避免重启后数据丢失;
    2. ID中加入时间戳前缀(如20240520_1001),即使Redis重置,也不会与历史ID重复。

3. 实战代码(Spring Boot+Redis)

3.1 核心依赖(pom.xml)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
3.2 Redis配置(application.yml)
spring:
redis:
host: 127.0.0.1
port: 6379
password:  # 若Redis有密码则填写
database: 0
lettuce:
pool:
max-active: 8 # 最大连接数
max-idle: 8  # 最大空闲连接数
3.3 核心代码实现
@Service
public class RedisIdGeneratorService {
@Autowired
private StringRedisTemplate redisTemplate;
// 业务前缀(避免不同业务ID冲突)
private static final String PREFIX_ORDER = "ORDER_";
private static final String PREFIX_COUPON = "COUPON_";
// Redis键(按业务区分)
private static final String REDIS_KEY_ORDER = "id_generator:order";
private static final String REDIS_KEY_COUPON = "id_generator:coupon";
// 生成订单ID(时间戳前缀+Redis自增ID)
public String generateOrderId() {
return generateId(PREFIX_ORDER, REDIS_KEY_ORDER);
}
// 生成优惠券ID
public String generateCouponId() {
return generateId(PREFIX_COUPON, REDIS_KEY_COUPON);
}
// 通用生成逻辑
private String generateId(String prefix, String redisKey) {
// 1. 获取当前日期前缀(yyyyMMdd,如20240520)
String datePrefix = new SimpleDateFormat("yyyyMMdd").format(new Date());
// 2. Redis原子递增(步长=1)
Long incrId = redisTemplate.opsForValue().increment(redisKey, 1);
// 3. 拼接ID(前缀+日期+6位自增ID,不足6位补0)
String suffix = String.format("%06d", incrId);
return prefix + datePrefix + "_" + suffix;
}
// 测试方法
public static void main(String[] args) {
// 模拟生成订单ID
RedisIdGeneratorService generator = new RedisIdGeneratorService();
String orderId = generator.generateOrderId();
System.out.println("订单ID:" + orderId); // 输出示例:ORDER_20240520_000101
}
}
3.4 调用示例
@Controller
@RequestMapping("/coupon")
public class CouponController {
@Autowired
private RedisIdGeneratorService idGeneratorService;
@PostMapping("/create")
public ResponseEntity<?> createCoupon() {// 生成优惠券ID(Redis方案)String couponId = idGeneratorService.generateCouponId();// 后续优惠券创建逻辑return ResponseEntity.ok("优惠券创建成功,ID:" + couponId);}}

4. 优点&缺点

  • 优点:
    1. 复用现有Redis组件,无需额外部署;
    2. 原子操作,ID唯一有序;
    3. 实现简单,支持业务前缀和日期前缀,可读性好;
    4. 性能高(Redis单机QPS万级+,支持主从复制)。
  • 缺点:
    1. 依赖Redis高可用(Redis宕机后无法生成ID,需主从+哨兵);
    2. Redis持久化配置不当,重启后ID可能重复;
    3. 高并发场景(10万+QPS)下,Redis可能成为瓶颈。

三、方案2:ZooKeeper分布式ID(基于持久顺序节点)

1. 核心原理

ZooKeeper支持创建“持久顺序节点”,每次创建节点时,ZooKeeper会自动在节点名称后追加一个有序编号(如id_order_00000001),截取该编号作为分布式ID:

2. 实战代码(Java+ZooKeeper)

2.1 核心依赖(pom.xml)
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.8.0</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></exclusion></exclusions>
</dependency>
2.2 核心代码实现
public class ZkIdGenerator {
// ZooKeeper连接地址
private static final String ZK_CONNECT_STR = "127.0.0.1:2181";
// 会话超时时间(3秒)
private static final int SESSION_TIMEOUT = 3000;
// 父节点路径(按业务区分)
private static final String PARENT_NODE_ORDER = "/id_generator/order";
private ZooKeeper zk;
// 初始化ZooKeeper连接
public ZkIdGenerator() throws IOException, InterruptedException {
zk = new ZooKeeper(ZK_CONNECT_STR, SESSION_TIMEOUT, event -> {
// 监听连接状态
if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
synchronized (this) {
this.notify();
}
}
});
synchronized (this) {
this.wait(); // 等待连接建立
}
// 创建父节点(不存在则创建)
createParentNode(PARENT_NODE_ORDER);
}
// 创建父节点
private void createParentNode(String parentNode) {
try {
if (zk.exists(parentNode, false) == null) {
// 持久节点(PERSISTENT)
zk.create(parentNode, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
}
} catch (Exception e) {
throw new RuntimeException("创建ZooKeeper父节点失败", e);
}
}
// 生成分布式ID
public Long generateId() throws Exception {
// 1. 创建临时顺序节点(EPHEMERAL_SEQUENTIAL)
String tempNode = PARENT_NODE_ORDER + "/temp_";
String nodePath = zk.create(tempNode, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
// 2. 截取有序编号(如"/id_generator/order/temp_0000000123" → "0000000123")
String sequence = nodePath.substring(nodePath.lastIndexOf("_") + 1);
// 3. 转换为Long型ID
Long id = Long.parseLong(sequence);
// 4. 删除临时节点(可选,避免节点过多)
zk.delete(nodePath, -1);
return id;
}
// 测试方法
public static void main(String[] args) throws Exception {
ZkIdGenerator generator = new ZkIdGenerator();
Long orderId = generator.generateId();
System.out.println("ZooKeeper生成订单ID:" + orderId); // 输出示例:123
}
}

3. 优点&缺点

  • 优点:
    1. 复用现有ZooKeeper组件,无需额外部署;
    2. 天然支持分布式协同,ID唯一有序;
    3. 临时顺序节点自动删除,无资源残留。
  • 缺点:
    1. 性能一般(ZooKeeper QPS千级,不适合高并发);
    2. 部署复杂(ZooKeeper需集群部署,保证高可用);
    3. 网络开销大(每次生成ID需创建节点、删除节点,涉及网络通信)。

四、避坑指南:2个方案的关键问题解决

1. Redis方案避坑

2. ZooKeeper方案避坑

  • 坑1:ZooKeeper集群脑裂导致ID重复;
    解决方案:部署ZooKeeper集群(至少3台节点),配置合理的选举参数(如tickTime=2000),避免脑裂。
  • 坑2:节点过多导致ZooKeeper性能下降;
    解决方案:用临时顺序节点(自动删除),或定时清理历史节点。

五、Redis vs ZooKeeper方案对比

特性Redis分布式IDZooKeeper分布式ID
性能高(QPS万级+)低(QPS千级)
实现复杂度简单(原子操作)中等(节点创建/删除)
部署成本低(单机即可,集群可选)高(需集群部署)
适用并发中高并发低并发
典型场景优惠券ID、活动ID、中小型订单ID配置中心标识、分布式锁关联ID

实战Tips

  1. 优先复用Redis:如果系统已部署Redis,优先选Redis方案(性能高、实现简单);
  2. Redis ID前缀:建议加入业务前缀+日期前缀,避免ID重复和泄露敏感信息;
  3. ZooKeeper慎用高并发:ZooKeeper适合低并发场景,高并发下建议选雪花算法或号段模式;
  4. 高可用配置:Redis/ZooKeeper作为ID生成组件,必须保证高可用(集群/主从),否则会阻塞业务。

下一篇预告

如果你的系统已经使用了分布式数据库(如TiDB、OceanBase),还有更简单的方案——直接使用分布式数据库自带的全局ID功能,无需额外开发。
下一篇我们拆解“分布式数据库方案”:TiDB和OceanBase的全局ID配置,帮你无缝集成分布式ID!
你在项目中用Redis还是ZooKeeper生成ID?评论区聊聊~

http://www.jsqmd.com/news/149950/

相关文章:

  • 虚拟偶像直播互动系统:背后的大模型推理架构
  • 分布式测试性能优化的系统性实践
  • 测试流程改进的变革管理:如何推动团队接受并践行新实践
  • 意图识别全解析:从入门到大模型应用,收藏级技术指南
  • 解锁n8n+大模型API:打造智能办公超级引擎
  • 5大主流LLM开源框架全方位对比与选型指南
  • 生成式AI在云负载测试中的革命性应用
  • 提示交互界面设计的10个直观化技巧,提示工程架构师必看!
  • RAG系统延迟太高?源头可能是缺少TensorRT优化
  • 基于微信小程序的学生实习与就业管理系统设计与实现毕业设计(源码+lw+部署文档+讲解等)
  • AI大模型架构师职业图谱:知识、技能与高薪前景
  • 图书馆古籍数字化加速:AI识别结合TensorRT推理
  • 图书馆古籍数字化加速:AI识别结合TensorRT推理
  • 奇林智媒如何重新定义成都线下品牌活动?10年案例积累告诉你 - 奇林智媒GEO
  • Python+Requests+Pytest+YAML+Allure实现接口自动化
  • LLaMA系列模型部署利器:NVIDIA TensorRT镜像详解
  • 学生资助在线管理软件开发微信小程序毕设源码(源码+lw+部署文档+讲解等)
  • 接口测试(postman、jmeter)
  • 使用Jmeter连接MySQL测试实战
  • GPU算力变现新路径:基于TensorRT镜像提供高性能推理API
  • 龙门锯厂家有哪些?2025龙门锯厂家实力盘点 - 栗子测评
  • AI应用架构师必知必会:智能Web3应用开发框架要点
  • 手机端大模型太耗电?云端TensorRT镜像分流减负
  • 智能家居控制中枢设计:轻量化TensorRT镜像集成
  • 大规模模型服务集群中TensorRT镜像的关键作用
  • 代码大全2第四章读书笔记
  • 智能写作辅助工具上线:文档生成延迟低于500ms
  • 花岗岩切割机厂家哪家好?2025切石机厂家推荐榜单 - 栗子测评
  • 如何甄别真正的操盘手?从成都三个现象级案例看奇林智媒的实战功底 - 奇林智媒GEO
  • 2025磨边机厂家有哪些?台面加工设备厂家口碑榜 - 栗子测评