本文主要是介绍基于redis生成自增流水号(格式:标志位 + 年月日时分秒 + 自增流水号),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近开发时,又遇到一个需求,后端需要生成自增的流水号,流水号格式一般就是:标志位 + 年月日时分秒 + 一定位数的流水号 组成,例如: T20190809135743000001 。
根据先前的查询和总结实现,现在对该需求的解决方法做一个整理记录。
先前在网上看各位大佬对自增流水号的处理,一般分成三种:
1. 通过在Java类中生成;
2.依托数据库自增函数生成;
3.依托redis自增生成
因为我当前项目中本身就整合redis,而且redis是单线程,且基于内存操作,速度快,实现自增流水号代码也简单,所以我选用的是第三种。
实现自增流水号,格式 标志位 + 年月日时分秒 + 一定位数的自增流水号 ,首先把这个分成两部分,一部分是前面的标志位 + 年月日时分秒,另一部分是一定位数的自增流水号,分别实现,最后拼接输出即可。
第一步:
生成流水号第一部分:标志位 + 年月日时分秒,这个很简单,不多说,代码如下:
StringBuffer sbuffer = new StringBuffer();sbuffer.append("T"); //标志位SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");sbuffer.append(sdf.format(new Date())); //年月日时分秒
第二步,调用redis的自增函数,获得流水号第二部分,自增
//设置6自增6位,用于补全操作private static final String STR_FORMAT = "000000";/*** redis流水号自增* @param key 自己设置,保存当前自增值* @param liveTime 在redis中的缓存时间,方法中设置单位(秒/分/天……)* @return*/public String incr(String key, long liveTime) {RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, stringRedisTemplate.getConnectionFactory());Long increment = entityIdCounter.getAndIncrement();if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间entityIdCounter.expire(liveTime, TimeUnit.DAYS); //设置自增值过期时间,liveTime 过期时间;TimeUnit.DAYS 过期时间单位,我这边设置为天}if (increment == 0) { increment = increment + 1;} else if (increment > 999999){ increment = 1L;}//位数不够,前面补0 DecimalFormat df = new DecimalFormat(STR_FORMAT); return df.format(increment);}
上述方法中,需要注意:
1.为保证每一天的流水号都是从01开始,所以我们的自增流水号对应的key必须要带上当天日期,例如:T20190809
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
String incKey = "T" + dateFormat.format(new Date());
2. 设置自增值的过期时间,即什么时候让redis销毁无用的保存自增值的key
3.保证流水号输出的位数不变,需要对自增值做位数补0操作
4.当前流水号大于设置的位数时,需要从头开始计数。
只要把上述两个代码片段结果拼接在一起,就能得到我们需要的自增流水号:T20190809135743000001
@Overridepublic String selectTaskNo() {//格式:T+yyyymmddHHmiss+6位流水StringBuffer sbuffer = new StringBuffer();sbuffer.append("T");SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");sbuffer.append(sdf.format(new Date()));SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");String incKey = "T" + dateFormat.format(new Date());String no = incr(incKey, 1);sbuffer.append(no);System.out.println(">>>>>>>>>>>" + sbuffer.toString());return sbuffer.toString();}
用 postMan 并发测试当前接口(并发值:100),控制台输出正确值,没有出现乱序现象
这篇关于基于redis生成自增流水号(格式:标志位 + 年月日时分秒 + 自增流水号)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!