package cn.iocoder.yudao.framework.common.util.number;
|
|
import java.util.concurrent.ThreadLocalRandom;
|
|
/**
|
* 业务编码(单据号 / 主数据编码)生成的公共约定。
|
*
|
* <p>需求:系统中所有自动生成的业务编码统一为「16 位纯数字」,且**随机生成、不使用自增/顺序**,
|
* 同时保证全系统唯一(任意两条编码都不重复)。
|
*
|
* <p>实现约定:
|
* <ul>
|
* <li>编码 = 随机 16 位数字(范围 0 ~ 10^16-1,左侧补 '0');</li>
|
* <li>唯一性由 Redis 集合 {@link #USED_SET_KEY} 查重保证:随机生成后写入集合,
|
* 写成功(返回 1)说明没用过才采用,否则重试;</li>
|
* <li>各生成点:见 {@link #randomCode()} 与 {@link #MAX_RETRY}。</li>
|
* </ul>
|
*
|
* <p>注意:Redis 集合丢失后,历史编码可能被重新随机命中;应用启动时会将库内已有编码
|
* 重新载入集合(见 yudao-server 的启动兜底)。
|
*/
|
public class BizNoUtils {
|
|
/**
|
* 已使用业务编码的 Redis 集合 KEY,用于随机编码查重,保证全系统唯一。
|
*/
|
public static final String USED_SET_KEY = "biz:code:used";
|
|
/**
|
* 业务编码的总长度:16 位
|
*/
|
public static final int CODE_LENGTH = 16;
|
|
/**
|
* 随机编码的空间上限(不含):10^16
|
*/
|
private static final long CODE_SPACE = 10_000_000_000_000_000L;
|
|
/**
|
* 生成随机编码时的最大重试次数(命中已用编码时重试)
|
*/
|
public static final int MAX_RETRY = 10;
|
|
/**
|
* 生成一个随机 16 位纯数字编码(左侧补 '0'),**不做查重**。
|
*
|
* <p>调用方需自行用 {@link #USED_SET_KEY} 查重,命中则重试。
|
*
|
* @return 随机 16 位纯数字编码
|
*/
|
public static String randomCode() {
|
return String.format("%0" + CODE_LENGTH + "d", ThreadLocalRandom.current().nextLong(CODE_SPACE));
|
}
|
|
}
|