订单号生成器

原理

订单号 = 前缀 + 日期 + (一个 1000-9999 之间的四位数字)

后面的四位数字,可以通过 jedis.incrBy() 来实现。

效能:最多可以在 1 秒钟创建 9000 个不重复单号

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* ID 生成器
*/
@Component
public class IdGenerator {
/**
* 生成器类型
*/
public enum Type {
NORMAL(""),
ORDER("OR"),
RETURN("RT"),
REFUND("RF");

private String prefix;

Type(String prefix) {
this.prefix = prefix;
}
}

private static String GENERATOR = "GENERATOR";
private static String FORMAT = "yyyyMMddHHmmss";

public String generate(Type type) {
String now = DateFormatUtils.format(new Date(), FORMAT);
String key = GENERATOR + ":" + type.name();
int counter = getCounter(key);
return String.format("%s%s%s", type.prefix, now, counter);
}

@Autowired
Jedis jedis;

/**
* 通过 redis 来获取累加器
* 根据 key 类型来获取累加数字
*
* @param key 类型
* @return 累加的数字
*/
private int getCounter(String key) {
int num;
String serial = jedis.get(key);
num = 1000;
if (serial != null && Integer.parseInt(serial) < 9999) {
num = jedis.incrBy(key, 1).intValue();
} else {
jedis.set(key, String.valueOf(num));
}
return num;
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@RunWith(SpringRunner.class)
@ComponentScan(basePackages = {"com.lyloou.order"})
@SpringBootTest
public class FlowApplicationTests {
@Autowired
IdGenerator idGenerator;

@Test
public void testGenerator() {
List<String> ids = Lists.newArrayList();
for (int i = 0; i < 10; i++) {
double delay = Math.random() * 1000;
Thread.sleep((long) delay);
ids.add(idGenerator.generate(IdGenerator.Type.ORDER));
}
System.out.println(Joiner.on(",\n").join(ids));
}
}

/** 运行结果:
OR202003261127151030,
OR202003261127161031,
OR202003261127171032,
OR202003261127181033,
OR202003261127181034,
OR202003261127191035,
OR202003261127191036,
OR202003261127191037,
OR202003261127201038,
OR202003261127211039
*/