数据库存储的是两个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. Android如何进行单元测试

    Menifest.xml中加入: <application>中加入: <uses-library android:name="android.test.runner&quo ...

  2. 图像处理之基础---图像缩放中的双线性插值c实现

    在进入频域变换之前, 我们还是轻松一下,再搞点平面上的变化来看看.这把选了一个双线性插值(Bilinear interpolation)来实现是源于看到了csdn上别人的问题, 权且实现一个函数,方便 ...

  3. web 开发之js---js 中的数组操作

    js数组元素的添加和删除一直比较迷惑,今天终于找到详细说明的资料了,先给个我测试的代码^-^var arr = new Array();arr[0] = "aaa";arr[1] ...

  4. JAVA实现N皇后问题(回溯法)

    package com.leetCode; /** * Follow up for N-Queens problem. Now, instead outputting board configurat ...

  5. neo4j 张一鸣 8

    头条关注 粉丝关系 张一鸣 8

  6. 多台Mac电脑使用同一个apple开发者账号测试

    因为公司有苹果一体机,家里有macbook和黑苹果台式机,多台电脑用同一个开发者账号,每次真机调试时都是选择直接reset,回到另外一台电脑,又要重新设置,太麻烦了.直到最近才设置三台电脑都可以,分享 ...

  7. 8-23 canvas专题

    8-23 canvas专题-了解外部框架的使用 学习要点 掌握画布内容的导出的toDataURL()方法 了解外部框架的使用 第八章内容介绍 在第八章中我们将对以前的知识进行简单的回顾,着重对canv ...

  8. 【HDU 3652】 B-numbers

    [题目链接] 点击打开链接 [算法] 数位DP f[i][j][k][l]表示i位数,第一位为j,除以13的余数为k,是/否包括子串“13”的方案数 当然,我们也可以先打表,然后,对于每次询问,二分即 ...

  9. nginx开发(二)配置mp4文件在线播放

    1: 第一步先开打nginx的文件夹遍历功能 vi /usr/local/nginx/conf/nginx.conf #编辑配置文件,在http {下面添加以下内容: autoindex on; #开 ...

  10. request.getRemoteAddr()和request.getRemoteHost()

    转自:https://www.cnblogs.com/aizj/p/7593209.html request.getRemoteAddr()是获得客户端的ip地址.request.getRemoteH ...