基于Redisson的RAtomicLong实现全局唯一工单号生成器

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 这次我们采用了 Redisson 的 RAtomicLong 来生成一个以固定字符加上年月为键的自增数。随后,将自增数转换为36进制字符串,以年月和36进制字符串拼接形成全局唯一的工单号。

最近几年,我一直从事的是运营平台业务开发。每天,我们都需要处理大量的工单配置工作。为了生成工单号,我们建立了一张专用的数据库表,用于记录和生成工单号。每次创建工单时,我们会查询这张表,根据年份字段、月份字段和模块编码找到最大的自增序列号。随后,我们将自增序列号加一,与模块编码、年月序列号拼接以生成工单号,并将相关信息写入表中。这种方法一直使用得很顺利,因为工单配置的量并不是特别大,一直都没有出现问题。然而,最近我们为第三方提供了一个工单推送的接口,他们一次性推送了大量的工单,这导致不仅生成了许多重复工单号,而且还引起了接口性能方面的问题。因此,我们决定对工单号生成方式进行改进,本文我们将介绍下我们新的生成方法。

redisson.jpg

实现思路

这次我们采用了 Redisson 的 RAtomicLong 来生成一个以固定字符加上年月为键的自增数。随后,将自增数转换为36进制字符串,以年月和36进制字符串拼接形成全局唯一的工单号。

代码实现

SerialIdService.java

@Service
@Slf4j
public class SerialIdService {
   
   

    private static final String ID_KEY = "xiuji:";
    private static final int BASE_36 = 36;

    private static final Integer SEQUENCE_LENGTH = 5;
    @Resource
    private RedissonClient redissonClient;

    public String workSerialId() {
   
   
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMM");
        String dateStr = LocalDate.now().format(formatter);
        //使用了Redisson的AtomicLong对象生成唯一序列号
        RAtomicLong atomicLong = redissonClient.getAtomicLong(ID_KEY+dateStr);
        //设置过期时间为35天
        if(atomicLong.get() == 0){
   
   
            atomicLong.expire(Duration.ofDays(35));
        }
        //将唯一序列号转换为36进制的字符串,长度为4位,用于减少ID的长度
        String sequenceStr = Long.toString(atomicLong.incrementAndGet(), BASE_36).toUpperCase();
        //36进制的序列号若小于4位,则用0补齐高位
        if (sequenceStr.length() < SEQUENCE_LENGTH) {
   
   
            sequenceStr = String.format("%4s", sequenceStr).replace(' ', '0');;
        }
        String serialId = dateStr+sequenceStr;

        log.info("生成的工单号:{}",dateStr+sequenceStr);
        return dateStr+sequenceStr;
    }

}

生成的工单号示例:

240121AXT6
240121AXT7
240121AXT8
240121AXT9
240121AXTA
240121AXTB
240121AXTC
240121AXTD
240121AXTE
240121AXTF
240121AXTG
240121AXTH
240121AXTI
240121AXTJ

总结

通过Redisson的RAtomicLong,我们成功实现了一个简单而强大的全局唯一工单号生成器。该生成器保证了唯一性,且在分布式环境中表现出色。在实际应用中,可以根据业务需求进行调整和扩展,以满足更复杂的场景。

目录
相关文章
|
前端开发 Java 数据库连接
分组序列@GroupSequenceProvider、@GroupSequence控制数据校验顺序,解决多字段联合逻辑校验问题【享学Spring MVC】(中)
分组序列@GroupSequenceProvider、@GroupSequence控制数据校验顺序,解决多字段联合逻辑校验问题【享学Spring MVC】(中)
|
14天前
|
存储 缓存 负载均衡
快递员送包裹与一致性哈希的关系
一致性哈希(Consistent Hashing)是一种用于分布式系统中数据分布和负载均衡的哈希技术。通过构建哈希环,将节点和数据映射到环上,实现动态扩展和高容错。具体步骤包括:1. 构建哈希环;2. 分配快递员;3. 分配快递包裹;4. 增加或减少节点时,仅需重定位少量数据,减少迁移成本。虚拟节点的引入进一步提高了数据分布的均匀性。
15 1
|
8月前
|
机器学习/深度学习 缓存 文字识别
印刷文字识别产品使用合集之标注阶段设定了两个独立的字段,但在返回的信息中却合并成了一个字段如何解决
印刷文字识别(Optical Character Recognition, OCR)技术能够将图片、扫描文档或 PDF 中的印刷文字转化为可编辑和可搜索的数据。这项技术广泛应用于多个领域,以提高工作效率、促进信息数字化。以下是一些印刷文字识别产品使用的典型场景合集。
|
8月前
|
存储 Java 关系型数据库
定时任务配置技巧:将表达式配置在业务员代码之外的方法
该文档介绍了三种不同的方法来定义和管理Java中的定时任务。首先,通过在数据库中创建一个表来存储定时任务的执行周期,并在Spring Boot应用中使用`@Scheduled`注解配合数据库查询来动态执行定时任务。其次,将定时任务的配置移动到Apollo配置中心,利用Apollo的配置能力来控制定时任务的执行。最后,使用Quartz框架并结合Apollo配置文件,动态地管理定时任务的触发间隔和执行时间。此外,还提到了在多机器环境中,可以使用分布式锁来避免任务重复,并推荐了xxl-JOB和elastic-job作为更专业的定时任务解决方案。
107 2
|
前端开发 安全 Java
分组序列@GroupSequenceProvider、@GroupSequence控制数据校验顺序,解决多字段联合逻辑校验问题【享学Spring MVC】(上)
分组序列@GroupSequenceProvider、@GroupSequence控制数据校验顺序,解决多字段联合逻辑校验问题【享学Spring MVC】(上)
分组序列@GroupSequenceProvider、@GroupSequence控制数据校验顺序,解决多字段联合逻辑校验问题【享学Spring MVC】(上)
39activiti - 设置下一节点签收人&&签收人查询代办事项
39activiti - 设置下一节点签收人&&签收人查询代办事项
67 0
|
存储 Java API
Java实现判断休息日和节假日
Java实现判断休息日和节假日
679 0
|
Java 数据库连接 测试技术
基于Springboot外卖系统10:公共字段填充功能+ThreadLocal模块改进
在新增员工时需要设置创建时间、创建人、修改时间、修改人等字段,在编辑员工时需要设置修改时间、修改人等字段。这些字段属于公共字段,也就是也就是在系统中很多表中都会有这些字段
151 0
|
JSON 前端开发 Java
基于Springboot外卖系统16:菜品修改模块+菜品信息回显+ID查询口味列表+组装数据并返回
在菜品管理列表页面点击修改按钮,跳转到修改菜品页面,在修改页面回显菜品相关信息并进行修改,最后点击确定按钮完成修改操作。
230 0
|
Shell 数据库 Python
【Django学习笔记 - 13】:关联查询(日期查询、一对一查询、一对多查询、多对多查询)
【Django学习笔记 - 13】:关联查询(日期查询、一对一查询、一对多查询、多对多查询)
479 0
【Django学习笔记 - 13】:关联查询(日期查询、一对一查询、一对多查询、多对多查询)