返回
RAtomicLong 助力全局唯一工单号生成
后端
2023-12-13 14:42:54
正文
在实际业务场景中,经常需要生成全局唯一的工单号,比如电商订单号、物流单号等。这些工单号通常由数字或字母组成,并且需要满足一定的格式要求,这使得手工生成工单号变得困难和容易出错。
因此,我们通常使用计算机程序来生成工单号。目前主流的工单号生成方法有两种:一种是使用数据库自增主键,另一种是使用分布式锁来保证工单号的唯一性。
第一种方法简单易行,但是存在并发冲突的问题,如果并发请求过多,可能会导致生成重复的工单号。第二种方法可以解决并发冲突的问题,但是实现起来比较复杂,需要借助第三方库或框架。
本文将介绍如何使用 Redisson 的 RAtomicLong 来实现一个全局唯一工单号生成器。Redisson 是一个基于 Redis 的分布式Java框架,提供了丰富的分布式数据结构和实用工具。
实现原理
Redisson 的 RAtomicLong 是一个分布式的原子长整型变量,它可以保证在并发环境下,对该变量的修改是原子的,即不会出现两个线程同时修改该变量的情况。
我们可以使用 RAtomicLong 来生成一个以固定字符加上年月为键的自增数。随后,将自增数转换为36进制字符串,以年月和36进制字符串拼接形成全局唯一的工单号。
代码示例
import io.redisson.api.RAtomicLong;
import io.redisson.api.RedissonClient;
public class OrderIdGenerator {
private RedissonClient redissonClient;
public OrderIdGenerator(RedissonClient redissonClient) {
this.redissonClient = redissonClient;
}
public String generateOrderId() {
// 使用年月作为键生成一个自增数
String key = String.format("order_id:%s%s", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMM")), UUID.randomUUID().toString());
RAtomicLong atomicLong = redissonClient.getAtomicLong(key);
// 将自增数转换为36进制字符串
String orderId = Long.toString(atomicLong.incrementAndGet(), 36);
// 以年月和36进制字符串拼接形成全局唯一的工单号
return String.format("%s%s", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMM")), orderId);
}
}
使用说明
使用上述代码示例生成的工单号具有以下特点:
- 全局唯一:由于使用了分布式锁,因此可以保证生成的工单号是全局唯一的。
- 不重复:由于使用了自增数,因此可以保证生成的工单号不重复。
- 格式固定:由于使用了固定字符加上年月和36进制字符串,因此可以保证生成的工单号具有固定的格式。
总结
本文介绍了如何使用 Redisson 的 RAtomicLong 来实现一个全局唯一工单号生成器。该方法简单易懂,易于实现,适用于各种场景。