在日常开发中,我们经常会遇到需要生成全局唯一递增 ID的场景,比如用户 ID、订单号、流水号等。使用数据库自增主键虽方便,但在分布式系统中容易成为瓶颈或冲突点。
一种高效且简单的方式是使用 Redis 的原子自增操作(INCR) 来生成递增 ID。本文将介绍在 Spring Boot 中如何结合 Redis 快速实现这一功能。
🧩 为什么选择 Redis 实现自增 ID?
- 原子性保障:Redis 的
INCR
操作天然支持原子性,无需额外加锁。 - 高性能:Redis 是内存型数据库,读写速度快,非常适合高并发场景。
- 分布式支持:多个服务节点共享同一个 Redis,自增 ID 不会重复。
- 简单易用:API 简洁,一行代码搞定。
🛠️ 实现步骤
1. 添加 Redis 依赖
<!-- Spring Boot Redis 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
确保你的 application.yml
中配置了 Redis:
spring: redis: host: localhost port: 6379
2. 编写 ID 生成服务类
使用 StringRedisTemplate
实现如下:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; @Service public class IdGeneratorService { @Autowired private StringRedisTemplate stringRedisTemplate; public Long getNextId(String keyPrefix) { String key = "incr:id:" + keyPrefix; return stringRedisTemplate.opsForValue().increment(key); } }
调用方式:
Long userId = idGeneratorService.getNextId("user"); Long orderId = idGeneratorService.getNextId("order");
⏱️ 可选优化:设置初始值和过期时间
如果希望每天从 1 开始编号(如流水号),可以设置初始值和过期时间:
stringRedisTemplate.opsForValue().setIfAbsent("incr:id:order", "1000"); stringRedisTemplate.expire("incr:id:order", Duration.ofDays(1));
📌 注意事项
- Redis 中的
INCR
会将 key 的值当作整数处理,不存在时自动从 0 开始。 - 自增 key 应该有明确的命名空间(如
incr:id:user
),防止冲突。 - 如果业务需要,可以在 ID 前加上时间戳或业务前缀,如
ORD20240518XXXX
。
✅ 总结
通过 Redis 的 INCR
命令,我们可以在 Spring Boot 项目中轻松实现一个高性能、线程安全、适用于分布式的全局自增 ID 生成器。相比数据库方案更轻量,且易于扩展。