基于 Redis+Redisson 实现分布式高可用编码生成器

​ 在分布式系统中,编码生成是一个高频且核心的场景 ------ 订单号、流水号、设备编码、业务单据号等,都要求全局唯一、规则可配置、高性能、支持定时重置。传统的数据库自增方案存在性能瓶颈,简单的本地生成又无法保证分布式唯一性,而硬编码的规则又缺乏灵活性。

​ 本文将分享一套基于 Redis+Redisson 实现的分布式编码生成器,该方案兼顾灵活性、高性能和分布式一致性,支持自定义编码规则、分布式唯一流水号、定时重置流水号等核心能力,可直接落地到生产环境。

核心需求与设计目标

在设计编码生成器前,我们先明确核心需求:

  1. 规则灵活:支持时间(年 / 月 / 日 / 时 / 分 / 秒 / 毫秒)、自增流水号、随机字符等占位符,自定义各部分长度;
  2. 分布式唯一:多实例部署下,生成的编码必须全局唯一,无重复;
  3. 高性能:支撑高并发场景,减少数据库依赖,降低 IO 开销;
  4. 容错兜底:Redis 重启 / 清空后,流水号能从数据库恢复,避免重复;
  5. 可重置:支持按 Cron 表达式定时重置流水号(如每日零点重置为 0);
  6. 易扩展:新增占位符规则时,代码改动最小化。

核心技术栈

基础框架:Spring Boot + MyBatis-Plus(数据持久化);

分布式缓存:Redis(流水号自增、规则缓存);

分布式锁:Redisson(保证并发安全、定时任务幂等);

定时任务:ThreadPoolTaskScheduler + Cron 表达式(流水号重置);

工具类:Hutool(Cron 解析、字符串处理);

性能优化:本地缓存 + Redis 缓存、异步批量持久化。

核心功能与实现原理

编码规则设计

编码规则采用 "固定字符 + 占位符" 的形式,支持以下占位符(可自定义扩展):

占位符 含义 示例(长度 4)
${yyyy} 2026
${MM} 月(补零) 01
${dd} 日(补零) 08
${hh} 时(24 小时制) 14
${mm} 分(补零) 59
${ss} 秒(补零) 07
${S} 毫秒(补零) 123(最大 3 位)
${X} 自增流水号 0001、00002
${UUU} 随机字符 A87、9z6

示例规则:JPC${hh}${UUU}${mm}${ss}${XXXX} → 生成结果:JPC14A8759070001

核心模块实现

规则解析模块

规则解析是编码生成的基础,核心逻辑通过栈结构 解析占位符,提取占位符类型和长度,代码核心逻辑在parseCodeRulegenerateConfigValue方法中:

  • 遍历规则字符串,通过栈匹配${}边界,提取内部的占位符(如XXXX);
  • 校验占位符合法性(必须是连续相同字符,如XXXX而非XxXX);
  • 根据占位符类型(如X= 流水号、U= 随机数)生成对应内容,补零或截取到指定长度。

核心亮点:解析逻辑与生成逻辑解耦,新增占位符只需在generateConfigValue的 switch 中添加分支,扩展性极强。

分布式流水号生成(核心)

流水号是编码唯一性的关键,采用 "Redis 自增 + 数据库兜底 + 分布式锁" 的方案:

Redis 自增 :通过redisTemplate.opsForValue().increment(seqKey, 1)实现高性能自增,Redis 的单线程特性保证自增原子性;

分布式锁防并发初始化:当 Redis 中流水号 KEY 不存在(自增返回 1)时,加 Redisson 分布式锁,从数据库查询该规则的最大流水号,初始化到 Redis,避免多实例并发初始化导致流水号重复;

数据库兜底 :Redis 重启 / 清空后,流水号从数据库max_seq字段加载,保证流水号不回退、不重复;

核心代码片段(流水号生成):

复制代码
private String generateSeqNum(CodeRule codeRule, int len) {
    String code = codeRule.getCode();
    String seqKey = REDIS_SEQ_PREFIX + code; 
    RLock initLock = redissonClient.getLock("seq:init:lock:" + code);
    try {
        Long seq = redisTemplate.opsForValue().increment(seqKey, 1);
        if (seq == 1) { // 首次初始化
            locked = initLock.tryLock(5, 10, TimeUnit.SECONDS);
            if (locked) {
                Long maxSeq = queryMaxSeqFromDb(code); // 从DB加载最大值
                if (maxSeq > 0) {
                    redisTemplate.opsForValue().set(seqKey, maxSeq);
                    seq = redisTemplate.opsForValue().increment(seqKey, 1);
                }
            }
        }
        saveBySeq(codeRule, seq); // 异步持久化
        return String.format("%0" + len + "d", seq);
    } finally {
        if (locked) initLock.unlock();
    }
}
定时重置流水号

支持按 Cron 表达式(如0 0 0 * * ?每日零点)重置流水号,核心类为SeqCronTaskManager

  1. 分布式定时任务 :基于ThreadPoolTaskScheduler创建定时任务,多实例部署下通过分布式锁保证同一时间只有一个实例执行重置;
  2. 幂等处理:通过 Redis 设置执行标识,避免同一 Cron 周期内重复重置;
  3. 统一 KEY 规则 :重置的流水号 KEY 统一为CODE_RULE_SEQ:规则标识,避免特殊字符导致的 Redis 客户端解析异常。
性能优化策略
  • 多级缓存 :编码规则先查本地缓存(CODE_RULE_CACHE),再查 Redis,最后查数据库,减少 DB 查询;
  • 异步批量持久化:流水号不是每次生成都写库,而是通过原子计数器累计到 100 次后异步批量更新,降低数据库 IO;

接口层设计

提供 RESTful 接口,支持编码规则的 CRUD、缓存刷新、编码生成等,核心生成接口:

复制代码
GET /code_rule/generateCode?code=JPC

请求示例:调用/code_rule/generateCode?code=JPC,规则为JPC${hh}${UUU}${mm}${ss}${XXXX},返回JPC14A8759070001

异常设计

异常处理
  • 分布式锁超时:抛出友好提示,避免无限阻塞;

  • Redis 类型异常:捕获 WRONGTYPE 异常,提示清理错误 KEY;

  • 空指针防护:缓存查询、数据库查询后均做非空校验;

  • 线程中断:捕获 InterruptedException,恢复线程中断状态。

redis配置

Redis 序列化配置(避免值序列化后为二进制,导致自增失败):

复制代码
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    template.setConnectionFactory(factory);
    return template;
}
完整代码地址

https://gitee.com/zh2358853434/short-chain.git

总结

这套编码生成器方案解决了系统中编码生成的核心痛点:

  • 灵活性:通过占位符支持自定义规则,新增规则成本低;
  • 唯一性:Redis 自增 + Redisson 分布式锁保证分布式唯一;
  • 高性能:多级缓存 + 异步持久化,支撑高并发;
  • 容错性:数据库兜底 + 类型校验,避免流水号丢失或异常;
  • 可配置:Cron 表达式支持灵活的流水号重置策略。
相关推荐
零叹17 小时前
Redis热Key——大厂是怎么解决的
数据库·redis·缓存·热key
win x18 小时前
Redis事务
数据库·redis·缓存
飞翔的小->子>弹->18 小时前
CMK、CEK
服务器·数据库·oracle
peixiuhui18 小时前
Iotgateway技术手册-7. 数据库设计
数据库·iotgateway·开源dotnet·arm工控板·开源网关软件·开源数据采集
成为你的宁宁18 小时前
【Zabbix 分布式监控实战指南(附图文教程):Server/Proxy/Agent 三者关系解析 + Proxy 部署、Agent 接入及取数路径验证】
分布式·zabbix
无心水18 小时前
【分布式利器:腾讯TSF】6、TSF可观测性体系建设实战:Java全链路Metrics+Tracing+Logging落地
java·分布式·架构·wpf·分布式利器·腾讯tsf·分布式利器:腾讯tsf
麦兜*18 小时前
【Spring Boot】 接口性能优化“十板斧”:从数据库连接到 JVM 调优的全链路提升
java·大数据·数据库·spring boot·后端·spring cloud·性能优化
qq_3344668618 小时前
U9补丁同步的时候报错
数据库
施嘉伟18 小时前
KSQL Developer 测试记录
数据库·kingbase