使用 Redis + Redisson 分布式锁来生成全局唯一、线程安全的带日期前缀的流水号的完整实现。

业务需求:创建一个流水号,

功能说明:

1,格式:orgCode + yyyyMMdd + 4位序号,

2,每天重新从 0001 开始

3,使用 Redisson 保证并发下分布式唯一,

4,Redis 存储当天序列号

示例代码

  1. Maven 依赖(如果还没加 Redisson):
java 复制代码
<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.17.7</version>
</dependency>
  1. 配置 RedissonClient(示例单节点):
java 复制代码
@Configuration
public class RedissonConfig {
    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://127.0.0.1:6379") // 修改为你自己的 Redis 地址
              .setDatabase(0);
        return Redisson.create(config);
    }
}
  1. 流水号工具类:
java 复制代码
@Component
public class SerialNumberGenerator {

    @Autowired
    private RedissonClient redissonClient;

    private static final String SERIAL_KEY_PREFIX = "serial:";

    public String generateSerialNumber(String orgCode) {
        String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String key = SERIAL_KEY_PREFIX + currentDate;

        String lockKey = "lock:serial:" + currentDate;
        RLock lock = redissonClient.getLock(lockKey);

        try {
            // 获取锁,最多等待5秒,锁自动释放时间为10秒
            if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
                RAtomicLong counter = redissonClient.getAtomicLong(key);

                // 如果是新的一天,重置为0
                if (!counter.isExists()) {
                    counter.set(0);
                    // 设置过期时间为2天,避免key一直存在
                    counter.expire(2, TimeUnit.DAYS);
                }

                long serial = counter.incrementAndGet();
                String formattedSerial = String.format("%04d", serial);
                return orgCode + currentDate + formattedSerial;
            } else {
                throw new RuntimeException("生成流水号失败:获取锁超时");
            }
        } catch (InterruptedException e) {
            throw new RuntimeException("生成流水号失败:线程中断", e);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

为什么需要 Redis 分布式锁?
不加锁的问题

Redis 是高并发环境下的共享存储,多个实例并发 get + set 操作有可能导致并发写丢失或重复编号。
加锁保证 :每次生成编号时只有一个线程在操作该 key 的值,从而保证原子性和唯一性

相关推荐
ma_king29 分钟前
入门 java 和 数据库
java·数据库·后端
jiayou644 小时前
KingbaseES 实战:审计追踪配置与运维实践
数据库
NineData16 小时前
NineData 迁移评估功能正式上线
数据库·dba
雨中飘荡的记忆20 小时前
大流量下库存扣减的数据库瓶颈:Redis分片缓存解决方案
java·redis·后端
NineData21 小时前
数据库迁移总踩坑?用 NineData 迁移评估,提前识别所有兼容性风险
数据库·程序员·云计算
赵渝强老师1 天前
【赵渝强老师】PostgreSQL中表的碎片
数据库·postgresql
全栈老石1 天前
拆解低代码引擎核心:元数据驱动的"万能表"架构
数据库·低代码
曲幽1 天前
FastAPI分布式系统实战:拆解分布式系统中常见问题及解决方案
redis·python·fastapi·web·httpx·lock·asyncio
倔强的石头_2 天前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
jiayou643 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库