数据库存储的是两个Long类型的复合主键。显示到页面的是一个27位的数字单号

 package com.yunyihenkey.common.idworker;

 /**
*
* @desc
* @author jon snow
* @version 1.0.0
*/
public class SuperSnowflakeIdWorker { public static class NextId {
private Long id1;
private Long id2; public NextId(Long id1, Long id2) {
this.id1 = id1;
this.id2 = id2;
} public Long getId1() {
return id1;
} public void setId1(Long id1) {
this.id1 = id1;
} public Long getId2() {
return id2;
} public void setId2(Long id2) {
this.id2 = id2;
} } /** 开始时间截(秒) */
public static final long birth = 1498939440L; /** 机器id所占的位数 */
public static final long workerIdBits = 20L; /** 序列在id中占的位数 */
public static final long sequenceBits = 43L; /** 支持的最大机器id (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
public static final long maxWorkerId = -1L ^ (-1L << workerIdBits); /** 序列最大值 */
public static final long sequenceMask = -1L ^ (-1L << sequenceBits); /** 工作机器ID(0~1048575 ) */
private long workerId; /** 秒内序列(0~8796093022207) */
private long sequence = 0L; /** 上次生成ID的时间截 */
private long lastTimestamp = -1L; public SuperSnowflakeIdWorker(long workerId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(
String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
this.workerId = workerId;
} public synchronized NextId nextId() {
long timestamp = timeGen(); // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format(
"Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
} // 如果是同一时间生成的,则进行秒内序列
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
// 秒内序列溢出
if (sequence == 0) {
// 阻塞到下一个秒,获得新的时间戳
timestamp = tilNextMillis(lastTimestamp);
}
}
// 时间戳改变,秒内序列重置
else {
sequence = 0L;
} // 上次生成ID的时间截
lastTimestamp = timestamp; // 移位并通过或运算拼到一起组成64位的ID
// long l = (workerId << sequenceBits) | sequence; // System.out.println(Long.toBinaryString(workerId) + ":+:" +
// Long.toBinaryString(sequence));
// String binaryString = Long.toBinaryString(l);
// System.out.println("生成:" + zero.substring(0, 63 - binaryString.length()) +
// binaryString);
// System.out.println("生成数字:" + l + ":原始数字:"
// + Long.valueOf(Long.toBinaryString(workerId) + Long.toBinaryString(sequence),
// 2) + "end"); // return new long[] { timestamp - birth, (workerId << sequenceBits) | sequence
// };
return new NextId(timestamp - birth, (workerId << sequenceBits) | sequence);
} /**
* 阻塞到下一个秒,直到获得新的时间戳
*
* @param lastTimestamp
* 上次生成ID的时间截
* @return 当前时间戳
*/
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
} private long timeGen() {
return System.currentTimeMillis() / 1000;
} /** 测试生成id */
public static void main(String[] args) { SuperSnowflakeIdWorker idWorker = new SuperSnowflakeIdWorker(666);
long currentTimeMillis = System.currentTimeMillis();
int times = 100000000;
for (int i = 0; i < times; i++) { // 获取一个复合主键id
// NextId nextId = idWorker.nextId();
idWorker.nextId(); // System.out.println(Long.toBinaryString(id)); // System.out.println("--------------------------------");
// String zero =
// "000000000000000000000000000000000000000000000000000000000000000";// 63个0
// String binaryString = Long.toBinaryString(nextId.getId2());
// BigInteger bigInteger = new BigInteger(
// Long.toBinaryString(nextId.getId1()) + zero.substring(0, 63 -
// binaryString.length()) + binaryString,
// 2);
// String string = bigInteger.toString();
// System.out.println("数据库存储:id1=" + nextId.getId1() + "::id2=" +
// nextId.getId2() + "::::页面显示订单号:" + string);
// String string2 = bigInteger.toString(2);
// System.out.println("id的比特字节::" + string2);
//
// int endIndex = string2.length() - 63;
// System.out
// .println("前端传过来的订单号:" + string + "" + " 解析-->id1=" +
// Long.valueOf(string2.substring(0, endIndex), 2)
// + "::id2=" + Long.valueOf(string2.substring(endIndex), 2));
} long cost = System.currentTimeMillis() - currentTimeMillis;
long l = times / (cost == 0 ? 1 : cost) * 1000;
System.out.println("\r\n耗时(ms):" + cost + ",速度(万每秒):" + (l / 10000)); } // /** 测试是否重复 */
// public static final ConcurrentHashMap<Object, Object> map = new
// ConcurrentHashMap<>(1000100);
/** 测试是否重复 */
// public static void main666(String[] args) {
// // 9个线程
// for (int i = 0; i < 9; i++) {
// new Thread(new Runnable() {
// @Override
// public void run() {
// MySnow idWorker = new MySnow(Thread.currentThread().getId());
// for (int j = 0; j < 1000000; j++) {
// NextId nextId = idWorker.nextId();
// Object put = map.put(Long.toString(nextId.getId1()) +
// Long.toString(nextId.getId2()), 1);
// if (put != null) {
// System.out.println("id重复!!!");
// }
// }
// System.out.println(Thread.currentThread().getId() + ",线程跑完");
// }
// }).start();
//
// }
//
// } }

全局唯一的支付和订单id生成算法的更多相关文章

  1. 分布式系统的唯一id生成算法你了解吗?

    在分库分表之后你必然要面对的一个问题,就是id咋生成? 因为要是一个表分成多个表之后,每个表的id都是从1开始累加自增长,那肯定不对啊. 举个例子,你的订单表拆分为了1024张订单表,每个表的id都从 ...

  2. 分布式全局不重复ID生成算法

    分布式全局不重复ID生成算法 算法全局id唯一id  在分布式系统中经常会使用到生成全局唯一不重复ID的情况.本篇博客介绍生成的一些方法. 常见的一些方式: 1.通过DB做全局自增操作 优点:简单.高 ...

  3. 分布式唯一ID生成算法-雪花算法

    在我们的工作中,数据库某些表的字段会用到唯一的,趋势递增的订单编号,我们将介绍两种方法,一种是传统的采用随机数生成的方式,另外一种是采用当前比较流行的“分布式唯一ID生成算法-雪花算法”来实现. 一. ...

  4. 唯一ID生成算法剖析

    https://mp.weixin.qq.com/s/E3PGP6FDBFUcghYfpe6vsg 唯一ID生成算法剖析 原创 cloudoxou 腾讯技术工程 2019-10-08    

  5. 美团技术分享:深度解密美团的分布式ID生成算法

    本文来自美团技术团队“照东”的分享,原题<Leaf——美团点评分布式ID生成系统>,收录时有勘误.修订并重新排版,感谢原作者的分享. 1.引言 鉴于IM系统中聊天消息ID生成算法和生成策略 ...

  6. 分布式 ID 生成算法 — SnowFlake

    一.概述 分布式 ID 生成算法的有很多种,Twitter 的 SnowFlake 就是其中经典的一种. SnowFlake 算法生成 ID 的结果是一个 64bit 大小的整数,它的结构如下图: 1 ...

  7. 理解分布式id生成算法SnowFlake

    理解分布式id生成算法SnowFlake https://segmentfault.com/a/1190000011282426#articleHeader2 分布式id生成算法的有很多种,Twitt ...

  8. 开源一个比雪花算法更好用的ID生成算法(雪花漂移)

    比雪花算法更好用的ID生成算法(单机或分布式唯一ID) 转载及版权声明 本人从未在博客园之外的网站,发表过本算法长文,其它网站所现文章,均属他人拷贝之作. 所有拷贝之作,均须保留项目开源链接,否则禁止 ...

  9. Twitter的SnowFlake分布式id生成算法

    二进制相关知识回顾 1.所有的数据都是以二进制的形式存储在硬盘上.对于一个字节的8位到底是什么类型 计算机是如何分辨的呢? 其实计算机并不负责判断数据类型,数据类型是程序告诉计算机该如何解释内存块. ...

随机推荐

  1. Appro DM8127 IPNC 挂载NFS遇到的问题及解决

    对于Appro DM8127 IPNC,默认的启动方式是NAND is used for booting kernel and NAND is used as root filesystem 为了调试 ...

  2. javascript总结02

    1 如何打开和关闭一个新的窗口? 2 Window对象的哪个属性能返回上一个浏览页面? 3 一次或多次执行一段程序的函数是什么? 定时函数 4 如何查找并访问节点? 5 给表格新增行和单元格的方法分别 ...

  3. 混合使用Delphi和C ++(附下载)

    您想将C ++添加到Delphi应用程序中吗?或者将Delphi代码添加到C ++应用程序中?这是如何做. 您可能不知道的一件事是如何在RAD Studio中集成C ++和Delphi语言.您可以将单 ...

  4. LightTable的结构(一)

    LightTable使用clojurescript来生成js,然后使用 node-webkit 来处理UI clojurescript非常适合做抽象程度很高的页面和编辑逻辑结构设计, 最近会对整体进行 ...

  5. SIM卡APDU指令【转】

    本文转载自:http://blog.csdn.net/hlx156/article/details/54136756 一个APDU可以是一个命令,也可以是命令的响应. 命令APDU的一般格式: CLA ...

  6. Apache Ignite——集合分布式缓存、计算、存储的分布式框架

    Apache Ignite内存数据组织平台是一个高性能.集成化.混合式的企业级分布式架构解决方案,核心价值在于可以帮助我们实现分布式架构透明化,开发人员根本不知道分布式技术的存在,可以使分布式缓存.计 ...

  7. 51Nod 1522 上下序列 —— 区间DP

    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1522 区间DP,从大往小加: 新加入一种数有3种加法:全加左边,全 ...

  8. jsp中一行多条数据情况

    1.实现效果:点击新增会在之前文本框后一直新增文本框并且保留新增的图片 效果图: 2.jsp代码: <table class="Business_Table"> < ...

  9. nginx配置改变默认访问路径

    在安装完nginx服务后,url访问的默认路径是安装的路径html文件夹下的内容,如果需要指定自定义的路径,需要配置nginx.conf文件内容,这样通过url访问就可以了,比如: http://12 ...

  10. 杂项-公司:Sun

    ylbtech-杂项-公司:Sun Sun Microsystems是IT及互联网技术服务公司(已被甲骨文收购)Sun Microsystems 创建于1982年.主要产品是工作站及服务器.1986年 ...