返回

RAtomicLong 助力全局唯一工单号生成

后端

正文

在实际业务场景中,经常需要生成全局唯一的工单号,比如电商订单号、物流单号等。这些工单号通常由数字或字母组成,并且需要满足一定的格式要求,这使得手工生成工单号变得困难和容易出错。

因此,我们通常使用计算机程序来生成工单号。目前主流的工单号生成方法有两种:一种是使用数据库自增主键,另一种是使用分布式锁来保证工单号的唯一性。

第一种方法简单易行,但是存在并发冲突的问题,如果并发请求过多,可能会导致生成重复的工单号。第二种方法可以解决并发冲突的问题,但是实现起来比较复杂,需要借助第三方库或框架。

本文将介绍如何使用 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 来实现一个全局唯一工单号生成器。该方法简单易懂,易于实现,适用于各种场景。