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

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注