尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

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

深入解析:【分布式利器:分布式ID】6、中间件方案:Redis/ZooKeeper分布式ID实现
📅 发布时间:2026/6/19 3:04:30

# 第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:

  • 原理:用Redis键(如order_id_generator)存储当前最大ID,每次生成ID时执行INCR key,返回递增后的ID;
  • 唯一性:Redis是单线程模型,INCR命令原子执行,不会出现并发冲突;
  • 有序性: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:

  • 原理:
    1. 创建父节点(如/id_generator/order);
    2. 每次生成ID时,在父节点下创建临时顺序节点(如/id_generator/order/temp_);
    3. 获取节点名称,截取末尾的有序编号(如00000001)作为ID;
    4. 删除临时节点(避免节点过多占用资源)。
  • 唯一性:ZooKeeper保证顺序节点的编号全局唯一;
  • 有序性:编号递增,支持排序。

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方案避坑

  • 坑1:Redis主从切换导致ID重复;
    解决方案:用Redis哨兵或集群模式,确保主从切换时数据同步完成,避免从库未同步最新自增ID就提供服务。
  • 坑2:Redis持久化配置不当导致ID重置;
    解决方案:开启AOF持久化(appendonly yes),并设置appendfsync everysec(每秒同步),确保自增ID数据不丢失。

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?评论区聊聊~

相关新闻

  • 基于Vue的招聘网站系统设计与开发81254(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
  • Postman如何测试WebService接口
  • 生成式AI在云负载测试中的革命性应用

最新新闻

  • 2026专业奢侈品回收综合实力榜 透明报价与口碑双优 - 工业品牌热点
  • Apkmod安全注意事项:合法使用APK逆向工程工具的道德和法律边界
  • HDPE双壁波纹管行业实力风云榜,2026口碑供应商横评 - mypinpai
  • Wox终极指南:如何用跨平台启动器提升10倍工作效率
  • Sharkive终极指南:如何在3DS和Switch上使用金手指代码库
  • PiliPlus完全指南:打造你的专属B站开源客户端

日新闻

  • 5分钟掌握Python进化算法:Geatpy高性能优化工具完全指南
  • Microchip 24AA044 EEPROM选型与应用全指南:从参数解析到实战编程
  • 华为的鸿蒙到底有多牛?为什么称作遥遥领先?

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号