使用 Redis 实现自增流水号
场景需求
项目上有个场景是客餐申请审核以后需要生成一个流水号,规则为:202202150001,202202150002,前几位为年月日,后四位依次递增。
想到 Redis 是基于内存操作的,而且速度比较快,也不占用数据库资源。于是便采用 Redis 实现的方式。
代码实现
形成规则工具类:
/**
* @author Greenarrow
* @date 2022-02-15 8:01
**/
public class SequenceUtil {
static final int DEFAULT_LENGTH = 4;
/**
* 格式化 key
* @param seq
* @return
*/
public static String getSequence(Long seq) {
String str = String.valueOf(seq);
int len = str.length();
// 取决于业务规模
if (len >= DEFAULT_LENGTH) {
return str;
}
int rest = DEFAULT_LENGTH - len;
StringJoiner stringJoiner = new StringJoiner("");
for (int i = 0; i < rest; i++) {
stringJoiner.add("0");
}
stringJoiner.add(str);
return stringJoiner.toString();
}
/**
* 获取当前年月日
* @return
*/
public static String getCurrentDate(){
LocalDate localDate = LocalDate.now();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
return df.format(localDate);
}
}
1
获取递增:
/**
* 获取递增
* @param key
* @return
*/
public long incr(String key){
return stringRedisTemplate.opsForValue().increment(key);
}
1
具体实现:
String currentDate = SequenceUtil.getCurrentDate();
String key = "serial.number:" + currentDate;
long sequence = redisService.incr(key);
String seq = SequenceUtil.getSequence(sequence);
StringJoiner sj = new StringJoiner("");
sj.add(currentDate).add(seq);
System.out.println(sj.toString());
1
输出结果:
202202150001
202202150002
202202150003
202202150004
1
本地 Redis 库中的数据:
扩展知识
Redis 序列化的策略有两种,分别是 StringRedisTemplate 和 RedisTemplate,其中StringRedisTemplate 用于操作字符串,RedisTemplate 使用的是JDK 默认的二进制序列化。
大家都知道 redis 序列化是将 key,value 值先转换为流的形式,再存储到 redis 中。
RedisTemplate 是使用的 JdkSerializationRedisSerializer 序列化,序列化后的值包含了对象信息,版本号,类信息等,是一串字符串,所以无法进行数值自增操作。
而 StringRedisTemplate 序列化策略是字符串的值直接转为字节数组,所以存储到 redis 中是数值,所以可以进行自增操作。
- END -