数据库存储的是两个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. cocos2d-x2.2.5走四棋儿源代码“开源”

    尊重开发人员的劳动成果.转载请注明From郝萌主 游戏简单介绍: 一款益智棋类游戏,通过两枚棋子对上敌方的一枚棋子便可击杀对方. 游戏界面精美简洁,游戏规则简单明了,AI聪明有趣. 人人对战,人机对战 ...

  2. selenium iframe 定位 qq空间说说

    selenium iframe 定位  qq空间说说

  3. Hibernate连接数据库

    包结构如下图所示(按图标进行对齐): 环境搭好后代码分为以下几步: /** * private static final Configuration CONFIGURATION; * private ...

  4. 【POI】T1 特工 szp

    T1 特工szp [问题描述] Byteotian 中央情报局 (BIA) 雇佣了许多特工. 他们每个人的工作就是监视另一名特工.Byteasar 国王需要进行一次秘密行动,所以他要挑选尽量多的信得过 ...

  5. flask核心对象Flask实例初探

    flask的核心程序就两个: werkzegu(WSGI)库,封装了http.web通信等最关键的wsgi功能②Jinja2是Python下一个被广泛应用的模版引擎,方便了html模板的创建和使用 而 ...

  6. Runtime ----- 带你上道

    在IOS开发和学习过程中,我们经常会接触到一个词: Runtime  .很多开发者对之既熟悉又陌生,基本都是浅尝辄止,达不到灵活使用的水平(话说开发中也确实不经常用..)本文和大家一起研究一下,Run ...

  7. emma中文显示乱码问题解决

    在Linux中如果使用mysql的图形客户端,个人感觉Emma还不错.但是emma默认用apt-get 安装的话,emma是不支持中文的,这个需要自己修改一下了配置文件,或者直接修改emma程序源文件 ...

  8. 【weiphp】安装中报错

    问题描述:安装的第三部报错“SQLSTATE[HY000]: General error: 2030 This command is not supported in the prepared sta ...

  9. deepin 安装 idea

    1.su root 2.sudo apt install idea 3.sudo vi /etc/hosts 最后一行添加 0.0.0.0 account.jetbrains.com 4.注册码 N7 ...

  10. laravel ORM 只开启created_at的方法

    class User extends Model { //重写setUpdatedAt方法 public function setUpdatedAt($value) { // Do nothing. ...