开发一个通用靠谱的单号生成器
单号生成器优化
之前我用Redis开发了一个通用的单号生成器,该单号生成器存了两个key。一个是序号递增的key,一个是记录日期的key。如果当前日期和Redis记录的日期不一致,单号就重置为1,重新从1开始递增。
因为有查日期和自增两个操作,生成序号的功能就需要加锁。起初加的是JVM级别的锁,但对于多实例的系统来说,JVM级别的锁会失效。于是引用了分布式锁。 private long getSuffixCode(String key) { RedissonClient redissonClient = redissonService.getRedissonClient(); RAtomicLong atomicVar = redissonClient.getAtomicLong(key); //获取当前日期 String todayStr = getTodayStr(); //获取redis记录的最大日期 String codeRecord = getCodeRecord(key); //创建分布式锁 RLock lock = redissonClient.getLock(REDIS_LOCK.concat(key)); long value = 0; try { //尝试加锁 if (lock.tryLock(10, 10, TimeUnit.SECONDS)) { if (!atomicVar.isExists()) { atomicVar.set(0); } if (StringUtils.isNotBlank(codeRecord)) { if (!isSameDay(todayStr, codeRecord)) { atomicVar.set(0); } } //记录日期 saveCodeRecord(key, todayStr); value = atomicVar.incrementAndGet(); //记录历史 String historyKey = key.concat(CODE_HISTORY_KEY); redisUtils.hset(historyKey, todayStr, String.valueOf(value)); } } catch (Exception e) { throw new ServerBizException("500", String.format("单号生成异常,key:[%s]", key)); } finally { if (lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); } } return value; }
这里使用了Redisson API的锁,并且增加功能,记录每天生成的最大序号。核心代码如上。
有兴趣的童鞋可以看看我这篇文章: 我写了一个简单通用的单号生成器
现在决定优化下,重新写一个静态调用的单号生成器。
生成器为静态类CodeUtils。 新单号生成器CodeUtils
主要调用方法如下: public static String generateFullCode(String prefix, int digit) { return generateFullCode(prefix, "yyyyMMdd", "GENERAL_CODE", true, digit); } /** * 单号生成器 * 通用单号生成器 格式 前缀 + YYMMDD + 序号 * * 列如 generatorCode("D","OVERALL",4),当前日期为:2022-08-12 * * 生成为:D202208120001 * * @param prefix 前缀 * @param module 业务模块 * @param digit 编码位数 * @return */ public static String generateFullCode(String prefix, String module, int digit) { return generateFullCode(prefix, "yyyyMMdd", module, true, digit); } /** * 单号生成器 * @param prefix 单号前缀 * @param datePattern 日期格式 * @param module 业务模块 * @param validateTenantId 是否需要验证当前租户id * @param digit 序号位数 * @return */ public static String generateFullCode(String prefix, String datePattern, String module, boolean validateTenantId, int digit) { String suffixCodeStr = getSuffixCodeStr(prefix, datePattern, module, validateTenantId, digit); String todayStr = getTodayStr(datePattern); String[] codes = {prefix, todayStr, suffixCodeStr}; return Stream.of(codes).collect(Collectors.joining()); }
这里我们定义了3种入参的方法generateFullCode,我们开看每种方法的解释: 1.generateFullCode(String prefix, int digit) 该方法两个入参,默认日期格式为:"yyyyMMdd",默认的module为:"GENERAL_CODE"。同时开启租户校验。能自定义前缀和定义编号位数。 2.generateFullCode(String prefix, String module, int digit) 与方法1的区别在于能自定义module。 3.generateFullCode(String prefix, String datePattern, String module, boolean validateTenantId, int digit) 通用的方法,能自定义单号前缀,日期格式,业务模块,租户id是否验证,序号位数。
这里我们每天按日期生成一个key,每个key对应当天日期。单号生成的核心代码如下: public static long generatorCode(String key) { RedissonClient redissonClient = redissonService.getRedissonClient(); RAtomicLong atomicVar = redissonClient.getAtomicLong(key); //设置过期时间2天 atomicVar.expire(2 ,TimeUnit.DAYS); //创建分布式锁 RLock lock = redissonClient.getLock(REDIS_LOCK.concat(key)); long value = 0; try { //尝试加锁 if (lock.tryLock(10, 10, TimeUnit.SECONDS)) { if (!atomicVar.isExists()) { atomicVar.set(0); } value = atomicVar.incrementAndGet(); } } catch (Exception e) { throw new ServerBizException("500", String.format("单号生成异常,key:[%s]", key)); } finally { if (lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); } } return value; }
如上代码,我们只需要一个key,就可以实现单号自增。功能还是每天递增,第二天重置。
我们设置的key如下: private static final String GET_NEXT_CODE_KEY = "sc:get_code:%s:%s_%s:%s"; private static final String REDIS_LOCK = "sc_code_generator_lock_";
这里用到了两个key。第一个是用来生成单号的,第二个是用来做分布式锁的。
在Redis上的目录如下:
这里Redis key组成形式为:sc:get_code固定值,加上租户id,加上单号前缀,加上模块,最后加上日期。
这里key我们保存两天,当前如果你要永远保存,用来看历史记录。key的有效期设置如下: //设置过期时间2天 atomicVar.expire(2 ,TimeUnit.DAYS);功能测试
调用示例代码如下: @Test public void testGeneratorCodeNew() { String prefix ="TEST"; String module = "C"; String dateStr = "yyyyMMdd"; String code = CodeUtils.generateFullCode(prefix, dateStr, module, false, 4); System.out.println(code); }
如上代码,我们生成了单号为TEST202212220001的单号。
世界杯最佳射手四条件!姆巴佩内马尔差点,梅西C罗也悬,他行吗世界杯明天开战,冠军大伙最喜欢猜,另一个就是谁会拿下最佳射手!最近,媒体发布最佳射手排名,本泽马,姆巴佩,内马尔,梅西,C罗,凯恩一批重量级球星赫然在列!但你们想的肯定和结果不一样
冬天上松下紧成穿搭新标杆,四种搭配示范,减龄还显瘦冬天怎么穿才能显瘦呢?一般冬天都是很厚重的衣服,那么怎么去用衣服打造出显瘦的效果,上松下紧的穿法就可以来尝试一下了。哪四种穿搭是上松下紧可借鉴1。大衣紧身裤大衣和紧身裤的穿搭有着很
说唱歌手的金光闪闪珠宝表演很多艺人都很浮华。是什么让嘻哈音乐脱颖而出?装饰的作用和如何展示自己非常重要。珠宝与麦克风和混音带一样是嘻哈音乐的主要元素。说唱歌手对黄金和冰的品味越来越高。对于一些人来说,闪闪发
auou艾遇清洁泥膜auou(艾遇)是一个国产新锐化妆品品牌,隶属于艾遇化妆品(苏州)有限公司。旗下产品包含面部护理和彩妆两方面,虽然名气还不算大,但是凭借着高性价比已经受到了不少消费者的关注和喜爱。
百万买她一夜(14)她将东西准备充足后,林泽辰就派助理林杨来接她了。舒晚提着包包,上了一辆迈巴赫。还以为林杨会直接将她送去林泽辰家里,没想到他竟然带她去了商场。几个造型师化妆师围着她,将她齐腰的大波浪
时尚品牌,潮宏基渠道逆势扩张布局,入局培育钻石铺路新增长点(报告出品方分析师中信证券杜一帆徐晓芳)布局时尚生态产业圈,国内领先年轻时尚品牌打造年轻时尚生态圈的时尚品牌潮宏基主营产品为珠宝首饰和时尚女包,旗下有CHJ潮宏基VENTI梵迪和F
去乌改玫淡化老式色素感,用双针机梦露小姐马上2023年一味用之前的老机器旧技术吸引新一代95后跟00后的客户是很难的更高端的审美更精湛的技术更舒适的仪器才能打动客户就像诺娇智造工厂新品Multi2系列双针机全抛机梦露小姐
人生的最后一站人生的最后一站在哪儿?我想我们都很清楚,要么我们到火葬场被火化,要么我们被埋进三尺黄土之中。坟墓,那是我们每个人的最后一站。不论是谁,不论你是高贵还是低贱,不论你是富裕还是贫穷,你
情感话题,余生你最想和谁在一起如果我想和你共度余生,我希望你能理解我,接纳我,愿意陪我一起度过一生。你要知道,是你,给了我余生。1你是我最喜欢的人如果爱一个人,就要将自己最好的东西给予对方,并且让对方感受到你的
郭麒麟经典语录在人生里看自己郭麒麟经典语录在人生里看自己对于郭麒麟的印象,是从不单一的定义自己。二十几的年少有着知天命般的通透。他站在巨人的肩膀上看天,却敢于搭一架梯子奔月。关于人生1。我就是我,我是郭麒麟。
动了真的爱,进了心的人,入了骨的情,放不下,也忘不了动了真的爱,入了心的人,进了骨的情,放不下,也忘不了思念一个人有多苦,爱一个人就有多真。思念一个人有多强烈,爱一个人就有多深。想念一个人心有多痛,爱一个人就有多无助。不是用心去爱过