UUID订单单号生成器

/** 订单号生成(NEW) **/
private static final AtomicInteger SEQ = new AtomicInteger(1000);
private static final DateTimeFormatter DF_FMT_PREFIX = DateTimeFormatter.ofPattern(“yyMMddHHmmssSS”);
private static ZoneId ZONE_ID = ZoneId.of(“Asia/Shanghai”);
public static String generateOrderNo(){
LocalDateTime dataTime = LocalDateTime.now(ZONE_ID);
if(SEQ.intValue()>9990){
SEQ.getAndSet(1000);
}
return dataTime.format(DF_FMT_PREFIX)+SEQ.getAndIncrement();
}

public static void main(String[] args) {List<String> orderNos = Collections.synchronizedList(new ArrayList<String>());IntStream.range(0,8000).parallel().forEach(i->{orderNos.add(generateOrderNo());});List<String> filterOrderNos = orderNos.stream().distinct().collect(Collectors.toList());System.out.println("生成订单数:"+orderNos.size());System.out.println("过滤重复后订单数:"+filterOrderNos.size());System.out.println("重复订单数:"+(orderNos.size()-filterOrderNos.size()));
}

我们的应用是跑在docker里面,而且每个docker容器内的应用端口都一样,不过网路IP不会存在重复的问题,至于进程也有存在重复的可能,对于UUID的方式之前吃过亏,总之吧,redis或DB也算是一种比较好的方式,不过独立性较差。。。
同时还有一个因素也很重要,就是所有涉及到订单号生成的应用都是在同一台宿主机(linux实体服务器)上, 所以就目前的系统架构我选用了IP的方式。
import org.apache.commons.lang3.RandomUtils;

import java.net.InetAddress;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class OrderGen2Test {

/** 订单号生成 **/
private static ZoneId ZONE_ID = ZoneId.of("Asia/Shanghai");
private static final AtomicInteger SEQ = new AtomicInteger(1000);
private static final DateTimeFormatter DF_FMT_PREFIX = DateTimeFormatter.ofPattern("yyMMddHHmmssSS");
public static String generateOrderNo(){LocalDateTime dataTime = LocalDateTime.now(ZONE_ID);if(SEQ.intValue()>9990){SEQ.getAndSet(1000);}return  dataTime.format(DF_FMT_PREFIX)+ getLocalIpSuffix()+SEQ.getAndIncrement();
}private volatile static String IP_SUFFIX = null;
private static String getLocalIpSuffix (){if(null != IP_SUFFIX){return IP_SUFFIX;}try {synchronized (OrderGen2Test.class){if(null != IP_SUFFIX){return IP_SUFFIX;}InetAddress addr = InetAddress.getLocalHost();//  172.17.0.4  172.17.0.199 ,String hostAddress = addr.getHostAddress();if (null != hostAddress && hostAddress.length() > 4) {String ipSuffix = hostAddress.trim().split("\\.")[3];if (ipSuffix.length() == 2) {IP_SUFFIX = ipSuffix;return IP_SUFFIX;}ipSuffix = "0" + ipSuffix;IP_SUFFIX = ipSuffix.substring(ipSuffix.length() - 2);return IP_SUFFIX;}IP_SUFFIX = RandomUtils.nextInt(10, 20) + "";return IP_SUFFIX;}}catch (Exception e){System.out.println("获取IP失败:"+e.getMessage());IP_SUFFIX =  RandomUtils.nextInt(10,20)+"";return IP_SUFFIX;}
}public static void main(String[] args) {List<String> orderNos = Collections.synchronizedList(new ArrayList<String>());IntStream.range(0,8000).parallel().forEach(i->{orderNos.add(generateOrderNo());});List<String> filterOrderNos = orderNos.stream().distinct().collect(Collectors.toList());System.out.println("订单样例:"+ orderNos.get(22));System.out.println("生成订单数:"+orderNos.size());System.out.println("过滤重复后订单数:"+filterOrderNos.size());System.out.println("重复订单数:"+(orderNos.size()-filterOrderNos.size()));
}

}

代码说明及几点建议
generateOrderNo()方法内不需要加锁,因为AtomicInteger内使用的是CAS自旋转锁(保证可见性的同时也保证原子性,具体的请自行了解)
getLocalIpSuffix()方法内不需要对不为null的逻辑加同步锁(双向校验锁,整体是一种安全的单例模式)
本人实现的方式并不是解决问题的唯一方式,具体解决问题需要视当前系统架构具体而论
任何测试都是必要的,我同事在前几次尝试解决这个问题后都没有自测,不测试有损开发专业性!

UUID订单单号生成器相关推荐

  1. vue前端自动生成编号或者订单单号(日期+随机数)

    created () {// 调用获取当前日期的方法加四位随机数 赋值表单中的项目编号this.form.number = this.getProjectNum() + Math.floor(Math ...

  2. 高可用高性能可扩展的单号生成方案

    作者:赵玉开,十年以上互联网研发经验,2013年加入京东,在运营研发部任架构师,期间先后主持了物流系统自动化运维平台.青龙数据监控系统和物流开放平台的研发工作,具有丰富的物流系统业务和架构经验.在此之 ...

  3. ecshop插件_ECSHOP和SHOPEX快递单号查询中通快递插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

  4. ECSHOP快递单号查询插件圆通V8.2专版

    本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅急送快递.德邦物流.百世快递.汇通快递.中通快递.天天快递等知 ...

  5. SHOPEX快递单号查询插件圆通V8.2专版

    SHOPEX快递物流单号查询插件特色 本SHOPEX快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅急送快递.德邦物流.百世 ...

  6. ECSHOP和SHOPEX快递单号查询申通插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

  7. ECSHOP和SHOPEX快递单号查询EMS插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

  8. ECSHOP和SHOPEX快递单号查询韵达插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

  9. ECSHOP和SHOPEX快递单号查询百世快递插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

  10. ECSHOP和SHOPEX快递单号查询顺丰插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

最新文章

  1. mysql的优化之table_open_cache 篇_mysql性能优化之table_open_cache
  2. 解决vscode中golang插件依赖安装失败问题
  3. Markdown常用转义字符
  4. 壁纸图片|2020年12月游戏图片大全
  5. P1103 书本整理
  6. [转载] 将整数k转换成实数python表达式_Python程序设计课后习题答案-第一单元
  7. HBuilder搭建Android模拟器
  8. oracle sql语句_7个维度查看oracle执行计划的sql语句执行效率
  9. labview的初步
  10. 计算机无法识别语音输入,我的电脑每次启动语音识别总是显示“由于语言配置不受支持,无法启动语音识别”;...
  11. 迅雷手机版苹果版_IOS手机迅雷下载(支持苹果手机和ipad)
  12. rclone 实现 GoogleDrive 同步至 OneDrive
  13. 科大讯飞,百度,思必驰,云知声四款识别引擎降噪算法性能对比
  14. python中如何查一个函数的用法_Python常见内置函数用法(三)
  15. 大神F1 Plus和中兴V5s哪个好
  16. 拯救者R7000系列(AMD) win10+ubuntu20双系统安装笔记,解决显卡、亮度控制、触控板问题
  17. Mac系统下使用SecureCRT连接Linux虚拟机及上传文件
  18. Windows操作系统各版本的历史 Windows系统历史版本简介
  19. Unity接入苹果内购(IAP)
  20. 【Statistics】HYPOTHESIS TEST(SIGNIFICANCE TEST)

热门文章

  1. 华钜同创:拯救你的亚马逊销量!你需要知道这些技巧
  2. VUE中根据文件后缀名显示对应的图标
  3. Python-docx 读写 Word 文档:插入图片、表格,设置表格样式,章节,页眉页脚等
  4. python批量处理word格式_用python批量处理word文档
  5. linux+新浪行情接口,新浪天气API接口
  6. iis服务器安装帝国网站,安装帝国cms如何配置iis
  7. 商业银行普惠金融可持续发展综合能力呈现梯队化,专项领域各有所长
  8. vlan协议中ISL与Dot1Q区别
  9. 综合latch 规避
  10. English:英语学习口诀(实用)