• 参考snowflake算法,基本思路:
  • 序列12位(更格式化的输出后,性能损耗导致每毫秒生成不了这么多,所以可以考虑减少这里的位,不过留着也并无影响)
  • 机器位10位
  • 毫秒为左移 22位

  • 上述几个做或运算后得出一个唯一的数,转10进制后,最大10位,最小7位,string.format来统一为10,format性能影响,导致性能降低3倍左右

FilUtils不想用的话,1太机器可以直接考虑使用1,多机器根据代码配置id
代码如下:

package net.gitosc.lianqu1990.utils.code;import net.gitosc.lianqu1990.utils.date.DateFormatUtils;
import net.gitosc.lianqu1990.utils.date.TimeMark;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;/*** 缺陷是,订单量没那么大,导致机器码|序列 后,一般都是4096* 通过将毫秒引入序列后修正* 后来加了format以后性能受损,比idcenter慢10倍,每秒可以生成50w,idcenter将近500w,不过这也是idcenter极限* 够用,暂不优化* @author hanchao* @date 2017/4/20 19:01*/
public class OrderNoCenter {public static final Logger logger = LoggerFactory.getLogger(OrderNoCenter.class);private static final String WORKERID_PATH = "/etc/workerId";private OrderNoCenter() {}private static class OrderNoCenterHolder{private static OrderNoCenter instance = new OrderNoCenter();}public static OrderNoCenter getInstance() {return OrderNoCenterHolder.instance;}/*** 节点 ID 默认取1*/private long workerId = 1;/*** 序列id 默认取1*/private long sequence = 1;/*** 机器标识位数*/private final long workerIdBits = 10L;/*** 机器ID最大值*/private final long maxWorkerId = -1L ^ (-1L << workerIdBits); //结果就是2的workerBits次方-1,能表示的最大数.全部1亦或10位0,就是0开头最后10位1/*** 毫秒内自增位*/private final long sequenceBits = 12L;/*** 机器ID偏左移12位*/private final long workerIdShift = sequenceBits;/*** 数据中心ID左移17位*/private final long datacenterIdShift = sequenceBits + workerIdBits;private final long sequenceMask = -1L ^ (-1L << sequenceBits);/*** 时间毫秒左移22位*/private final long timestampLeftShift = sequenceBits + workerIdBits;private long lastTimestamp = -1L;public void initParam() {// 从默认位置读取workerId,最大1024try {File conf = new File(WORKERID_PATH);if(conf.exists()){String str = FileUtils.readFileToString(conf);workerId = Integer.parseInt(str);}else{logger.warn(" worker id not found,will use default value...");}} catch(Exception e){e.printStackTrace();}logger.info(" worker id is {}",workerId);if (workerId < 0 || workerId > maxWorkerId) {throw new IllegalArgumentException("workerId is illegal: "+ workerId);}}public long getWorkerId() {return workerId;}public long getTime() {return System.currentTimeMillis();}public String create() {return nextNo();}/*** 获取id 线程安全** @return*/private synchronized String nextNo() {long timestamp = timeGen();// 时间错误if (timestamp < lastTimestamp) {throw new IllegalStateException("Clock moved backwards.");}// 当前毫秒内,则+1if (lastTimestamp == timestamp) {// 当前毫秒内计数满了,则等待下一秒sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0;}lastTimestamp = timestamp;// ID偏移组合生成最终的ID,并返回ID,最大十位数long id = ((timestamp % 1000) << timestampLeftShift) | (workerId << workerIdShift) | sequence;String timestampStr = DateFormatUtils.NUMBER_FORMAT.format(timestamp);return timestampStr+String.format("%010d",id);}/*** 等待下一个毫秒的到来** @param lastTimestamp* @return*/private long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}/*** 最大十位,最小7位,补0format*//*public void test(){String t = String.valueOf((1L << 22) | (1 << 12) | 0);String t1 = String.valueOf((999L << 22) | (1023 << 12) | 0);System.out.println(DateFormatUtils.NUMBER_FORMAT.format(System.currentTimeMillis())+"-"+t);System.out.println(DateFormatUtils.NUMBER_FORMAT.format(System.currentTimeMillis())+"-"+t1);long l1 = (1L << 22) | (1 << 12) | 0;long l2 = (999L << 22) | (1023 << 12) | 0;System.out.println(l1);System.out.println(l2);System.out.println(String.format("%010d",l1));System.out.println(String.format("%010d",l2));}*/public static void main(String[] args){for (int i = 0; i < 100; i++) {System.out.println(OrderNoCenter.getInstance().create());}//性能测试TimeMark mark = new TimeMark();for (int i = 0; i < 1000000; i++) {OrderNoCenter.getInstance().create();}mark.simplePrint();mark.mark();for (int i = 0; i < 1000000; i++) {IdCenter.getInstance().getId();}mark.simplePrint();}
}

缺少代码的话,请直接使用我的附件代码

附件:
代码代码代码代码代码点击下载下载

转载于:https://www.cnblogs.com/luochengqiuse/p/6747895.html

业务订单号生成算法,每秒50W左右,不同机器保证不重复,包含日期可读性好...相关推荐

  1. 快速订单号生成(两秒左右10万条数据无重复)

    订单号生成 在开发当中我想大部分程序员都会做商城类的项目,其中订单号是一个相对比较重要的数据,在用户下单是不允许有重复订单生成的. 我给大家提供了一个生成订单的方法,希望对您有所帮助!!!!!!!!! ...

  2. 电商平台订单号生成策略

    订单是整个电子商务的核心.整个电子商务的流程也是围绕订单的状态执行的.这篇博客主要向大家介绍订单号的生成方式. 现在大型电商网站大多都有好几种下单途径.比如:通过Web网站下单,通过打电话到呼叫中心下 ...

  3. Python模拟订单号生成

    模拟订单号生成 为了产生不冲突的订单号,本次测试订单生成逻辑比较简单:当天时间拼接自增数列 from datetime import datetime def set_flow():base_code ...

  4. java唯一订单号_java web在高并发和分布式下实现订单号生成唯一的解决方案

    方案一: 如果没有并发,订单号只在一个线程内产生,那么由于程序是顺序执行的,不同订单的生成时间戳正常不同,因此用时间戳+随机数(或自增数)就可以区分各个订单.如果存在并发,且订单号是由一个进程中的多个 ...

  5. 快速分辨订单号生成工具

    为了人工可以快速分辨订单号是下单还是退款.来自哪家支付机构等 /*** 微信订单号生成* @param userId* @return*/public static String wxOrderNo( ...

  6. 订单号生成的一些想法

    背景 早上QA小姐姐发现线上有个报错,过去一看,采购单号生成异常,后台duplicate key,也就是说生成了重复单号.这个模块之前不是我写的(这个哥们刚离职了),而后来的领料单号的生成我重新写了下 ...

  7. 不重复订单号生成的方法

    第一种        GUID  由算法自动生成下 理论上能产生全球唯一的值   不过对于用户记订单号不方便 Console.WriteLine(System.Guid.NewGuid());     ...

  8. 支付不重复订单号生成

    最近的项目中支付的订单号是使用附加项目中的工具做的,是一种带数据库自增形式的订单号,开始测试的时候没有任何问题,但是再高并发的实际应用中还是有不小的问题,只怪自己考虑太少,必须在高并发模式下保证订单号 ...

  9. java并发订单号生成

    单机并发下订单的生成策略,订单号以年月日开头序 import java.time.Instant; import java.util.HashSet; import java.util.Set; im ...

最新文章

  1. GAN:「太难的部分我就不生成了,在下告退」
  2. Windows 驱动发展基金会(九)内核函数
  3. boost::iota相关的测试程序
  4. MySQL数据库(六) 一一 基本操作之事物和索引
  5. C++中4种方式把字符串和数字连接起来(转载)
  6. 大话Synchronized及锁升级
  7. WIN8系统安装软件时提示“扩展属性不一致“的解决方法
  8. xml解析总结-常用需掌握
  9. Spark常用算子讲解一
  10. 有/无外网情况下linux安装宋体
  11. app如何添加广告位 uni_广告以及广告位的详细说明(如何在APP中添加广告)
  12. 基于matlab分析的商业保险案例
  13. php获取企业微信聊天内容,微信企业号开发获取用户信息的介绍
  14. z-index什么意思
  15. 2019,关于我的故事
  16. SVN代码迁移到Gitlab(保留SVN的提交记录)
  17. Python正则表达式在线练习(网页版)和离线练习(本地版)
  18. negroni-gzip源码分析
  19. easy-mock 官网,最新网址!
  20. JAVA做语言国际化

热门文章

  1. 【嵌入式】嵌入式天地博客汇总
  2. 【Qt】Qt中JSON简介
  3. 【Linux】一步一步学Linux——nm命令(250)
  4. linux xps 13 wifi,XPS13-9350安装linux以及网卡连接失败修复的临时方案
  5. ucos 消息队列代码详解_用python实现 多进程队的列数据处理详解,零基础记得都收藏哦
  6. web_reverse_proxy -- haproxy
  7. Qt程序打包发布方法(使用官方提供的windeployqt工具)
  8. 算法学习笔记2022.1.8
  9. Mysql(8)——as和distinct和where的用法
  10. Ubuntu-Python安装 scipy,numpy,matplotlib