最近几年,我一直从事的是运营平台业务开发。每天,我们都需要处理大量的工单配置工作。为了生成工单号,我们建立了一张专用的数据库表,用于记录和生成工单号。每次创建工单时,我们会查询这张表,根据年份字段、月份字段和模块编码找到最大的自增序列号。随后,我们将自增序列号加一,与模块编码、年月序列号拼接以生成工单号,并将相关信息写入表中。这种方法一直使用得很顺利,因为工单配置的量并不是特别大,一直都没有出现问题。然而,最近我们为第三方提供了一个工单推送的接口,他们一次性推送了大量的工单,这导致不仅生成了许多重复工单号,而且还引起了接口性能方面的问题。因此,我们决定对工单号生成方式进行改进,本文我们将介绍下我们新的生成方法。
这次我们采用了 Redisson 的 RAtomicLong 来生成一个以固定字符加上年月为键的自增数。随后,将自增数转换为36进制字符串,以年月和36进制字符串拼接形成全局唯一的工单号。
SerialIdService.java
@Service@Slf4jpublic 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; }}
生成的工单号示例:
240121AXT6240121AXT7240121AXT8240121AXT9240121AXTA240121AXTB240121AXTC240121AXTD240121AXTE240121AXTF240121AXTG240121AXTH240121AXTI240121AXTJ
通过Redisson的RAtomicLong,我们成功实现了一个简单而强大的全局唯一工单号生成器。该生成器保证了唯一性,且在分布式环境中表现出色。在实际应用中,可以根据业务需求进行调整和扩展,以满足更复杂的场景。
本文链接:http://www.28at.com/showinfo-26-68323-0.html基于Redisson的RAtomicLong实现全局唯一工单号生成器
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: JDK17 与 JDK11 特性差异浅谈