在日常开发中,我们经常会遇到需要生成全局唯一递增 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 生成器。相比数据库方案更轻量,且易于扩展。
