全局唯一的支付和订单id生成算法

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

  1 package com.yunyihenkey.common.idworker;
  2 
  3 /**
  4  * 
  5  * @desc
  6  * @author jon snow
  7  * @version 1.0.0
  8  */
  9 public class SuperSnowflakeIdWorker {
 10 
 11     public static class NextId {
 12         private Long id1;
 13         private Long id2;
 14 
 15         public NextId(Long id1, Long id2) {
 16             this.id1 = id1;
 17             this.id2 = id2;
 18         }
 19 
 20         public Long getId1() {
 21             return id1;
 22         }
 23 
 24         public void setId1(Long id1) {
 25             this.id1 = id1;
 26         }
 27 
 28         public Long getId2() {
 29             return id2;
 30         }
 31 
 32         public void setId2(Long id2) {
 33             this.id2 = id2;
 34         }
 35 
 36     }
 37 
 38     /** 开始时间截(秒) */
 39     public static final long birth = 1498939440L;
 40 
 41     /** 机器id所占的位数 */
 42     public static final long workerIdBits = 20L;
 43 
 44     /** 序列在id中占的位数 */
 45     public static final long sequenceBits = 43L;
 46 
 47     /** 支持的最大机器id (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
 48     public static final long maxWorkerId = -1L ^ (-1L << workerIdBits);
 49 
 50     /** 序列最大值 */
 51     public static final long sequenceMask = -1L ^ (-1L << sequenceBits);
 52 
 53     /** 工作机器ID(0~1048575 ) */
 54     private long workerId;
 55 
 56     /** 秒内序列(0~8796093022207) */
 57     private long sequence = 0L;
 58 
 59     /** 上次生成ID的时间截 */
 60     private long lastTimestamp = -1L;
 61 
 62     public SuperSnowflakeIdWorker(long workerId) {
 63         if (workerId > maxWorkerId || workerId < 0) {
 64             throw new IllegalArgumentException(
 65                     String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
 66         }
 67         this.workerId = workerId;
 68     }
 69 
 70     public synchronized NextId nextId() {
 71         long timestamp = timeGen();
 72 
 73         // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
 74         if (timestamp < lastTimestamp) {
 75             throw new RuntimeException(String.format(
 76                     "Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
 77         }
 78 
 79         // 如果是同一时间生成的,则进行秒内序列
 80         if (lastTimestamp == timestamp) {
 81             sequence = (sequence + 1) & sequenceMask;
 82             // 秒内序列溢出
 83             if (sequence == 0) {
 84                 // 阻塞到下一个秒,获得新的时间戳
 85                 timestamp = tilNextMillis(lastTimestamp);
 86             }
 87         }
 88         // 时间戳改变,秒内序列重置
 89         else {
 90             sequence = 0L;
 91         }
 92 
 93         // 上次生成ID的时间截
 94         lastTimestamp = timestamp;
 95 
 96         // 移位并通过或运算拼到一起组成64位的ID
 97         // long l = (workerId << sequenceBits) | sequence;
 98 
 99         // System.out.println(Long.toBinaryString(workerId) + ":+:" +
100         // Long.toBinaryString(sequence));
101         // String binaryString = Long.toBinaryString(l);
102         // System.out.println("生成:" + zero.substring(0, 63 - binaryString.length()) +
103         // binaryString);
104         // System.out.println("生成数字:" + l + ":原始数字:"
105         // + Long.valueOf(Long.toBinaryString(workerId) + Long.toBinaryString(sequence),
106         // 2) + "end");
107 
108         // return new long[] { timestamp - birth, (workerId << sequenceBits) | sequence
109         // };
110         return new NextId(timestamp - birth, (workerId << sequenceBits) | sequence);
111     }
112 
113     /**
114      * 阻塞到下一个秒,直到获得新的时间戳
115      * 
116      * @param lastTimestamp
117      *            上次生成ID的时间截
118      * @return 当前时间戳
119      */
120     protected long tilNextMillis(long lastTimestamp) {
121         long timestamp = timeGen();
122         while (timestamp <= lastTimestamp) {
123             timestamp = timeGen();
124         }
125         return timestamp;
126     }
127 
128     private long timeGen() {
129         return System.currentTimeMillis() / 1000;
130     }
131 
132     /** 测试生成id */
133     public static void main(String[] args) {
134 
135         SuperSnowflakeIdWorker idWorker = new SuperSnowflakeIdWorker(666);
136         long currentTimeMillis = System.currentTimeMillis();
137         int times = 100000000;
138         for (int i = 0; i < times; i++) {
139 
140             // 获取一个复合主键id
141             // NextId nextId = idWorker.nextId();
142             idWorker.nextId();
143 
144             // System.out.println(Long.toBinaryString(id));
145 
146             // System.out.println("--------------------------------");
147             // String zero =
148             // "000000000000000000000000000000000000000000000000000000000000000";// 63个0
149             // String binaryString = Long.toBinaryString(nextId.getId2());
150             // BigInteger bigInteger = new BigInteger(
151             // Long.toBinaryString(nextId.getId1()) + zero.substring(0, 63 -
152             // binaryString.length()) + binaryString,
153             // 2);
154             // String string = bigInteger.toString();
155             // System.out.println("数据库存储:id1=" + nextId.getId1() + "::id2=" +
156             // nextId.getId2() + "::::页面显示订单号:" + string);
157             // String string2 = bigInteger.toString(2);
158             // System.out.println("id的比特字节::" + string2);
159             //
160             // int endIndex = string2.length() - 63;
161             // System.out
162             // .println("前端传过来的订单号:" + string + "" + " 解析-->id1=" +
163             // Long.valueOf(string2.substring(0, endIndex), 2)
164             // + "::id2=" + Long.valueOf(string2.substring(endIndex), 2));
165         }
166 
167         long cost = System.currentTimeMillis() - currentTimeMillis;
168         long l = times / (cost == 0 ? 1 : cost) * 1000;
169         System.out.println("\r\n耗时(ms):" + cost + ",速度(万每秒):" + (l / 10000));
170 
171     }
172 
173     // /** 测试是否重复 */
174     // public static final ConcurrentHashMap<Object, Object> map = new
175     // ConcurrentHashMap<>(1000100);
176     /** 测试是否重复 */
177     // public static void main666(String[] args) {
178     // // 9个线程
179     // for (int i = 0; i < 9; i++) {
180     // new Thread(new Runnable() {
181     // @Override
182     // public void run() {
183     // MySnow idWorker = new MySnow(Thread.currentThread().getId());
184     // for (int j = 0; j < 1000000; j++) {
185     // NextId nextId = idWorker.nextId();
186     // Object put = map.put(Long.toString(nextId.getId1()) +
187     // Long.toString(nextId.getId2()), 1);
188     // if (put != null) {
189     // System.out.println("id重复!!!");
190     // }
191     // }
192     // System.out.println(Thread.currentThread().getId() + ",线程跑完");
193     // }
194     // }).start();
195     //
196     // }
197     //
198     // }
199 
200 }

猜你喜欢

转载自www.cnblogs.com/wulm/p/9166022.html