package jeffery;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID; /**
* Created by jeffery on 2016/5/20.
* tweeter的snowflake 移植到Java.参考资料:https://github.com/twitter/snowflake
* id构成: 42位的时间前缀 + 10位的节点标识 + 12位的sequence避免并发的数字(12位不够用时强制得到新的时间前缀)
* id单调递增,长整型
* 注意这里进行了小改动: snowkflake是5位的datacenter加5位的机器id; 这里变成使用10位的机器id
* snowkflake当时间调整时将拒绝分配ID,这里改成分配UUID的tMostSignificantBits
* 通过取服务器名中的编号来分配机器id,实现了去状态化
* 使用:long id = IdWorker.nextId();
*/
public final class IdWorker {
private static final long workerId;//每台机器分配不同的id
private static final long epoch = 1472693086614L; // 时间起始标记点,作为基准,一般取系统的最近时间
private static final long workerIdBits = 10L; // 机器标识位数
private static final long maxWorkerId = -1L ^ -1L << workerIdBits;// 机器ID最大值: 1023
private static long sequence = 0L; // 0,并发控制
private static final long sequenceBits = 12L; //毫秒内自增位 private static final long workerIdShift = sequenceBits; // 12
private static final long timestampLeftShift = sequenceBits + workerIdBits;// 22
private static final long sequenceMask = -1L ^ -1L << sequenceBits; // 4095,111111111111,12位
private static long lastTimestamp = -1L; static {
String hostName = null;
try {
InetAddress netAddress = InetAddress.getLocalHost();
hostName = netAddress.getHostName();
} catch (UnknownHostException e) {
}
if (null != hostName && !"".equals(hostName)) {
String hostNo = "";
for (int i = 0; i < hostName.length(); i++) {
if (hostName.charAt(i) >= 48 && hostName.charAt(i) <= 57) {
//取最后一组数字
if ("".equals(hostNo) || (hostName.charAt(i - 1) >= 48 && hostName.charAt(i - 1) <= 57))
hostNo += hostName.charAt(i);
else {
hostNo = "";
hostNo += hostName.charAt(i);
}
}
}
if (null != hostNo && !"".equals(hostNo)) {
workerId = Integer.parseInt(hostNo) % maxWorkerId;
} else {
workerId = 1;//TODO:当机器名不包含编号时,采用手动编号,需要在配置文件中指定 } } else {
workerId = 1;
}
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
} public static synchronized long nextId() {
long timestamp = timeGen();
if (lastTimestamp == timestamp) { // 如果上一个timestamp与新产生的相等,则sequence加一(0-4095循环); 对新的timestamp,sequence从0开始
sequence = sequence + 1 & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);// 重新生成timestamp
}
} else {
sequence = 0;
} if (timestamp < lastTimestamp) {
UUID uuid = UUID.randomUUID();
return uuid.getMostSignificantBits();
} lastTimestamp = timestamp;
return timestamp - epoch << timestampLeftShift | workerId << workerIdShift | sequence;
} /**
* 等待下一个毫秒的到来, 保证返回的毫秒数在参数lastTimestamp之后
*/
private static long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
} /**
* 获得系统当前毫秒数
*/
private static long timeGen() {
return System.currentTimeMillis();
} }

基于Twitter-Snowflake的java改进版,去状态化实现的更多相关文章

  1. Twitter Snowflake 的Java实现

    在关闭显示的情况下, 可以达到每毫秒3万个的生成速度 /** * An Implementation of Twitter Snowflake ID Generator */ public class ...

  2. 交易所频频跑路?Baccarat去中心化交易平台助力资金安全

    过去,黑客攻击可能是交易所跑路的最常见原因.自OKEx事件以来,这些交易所暂停提币或跑路还多了一个原因,就是因创始人正在协助调查. 据不完全统计,自OKEx于10月16日宣布暂停提币后不到两个月,已经 ...

  3. NGK公链:去中心化交易+挖矿生态体系共舞

    NGK生态公链是一个安全.透明.专业的去中心化商业应用平台.作为一条具有技术信任甚至是公众信任的公链,NGK以区块链技术为支撑,利用区块链透明.公正.公开.数据不可篡改.分布式存储.可追溯等技术优势, ...

  4. 基于Twitter的Snowflake算法实现分布式高效有序ID生产黑科技(无懈可击)

    参考美团文档:https://tech.meituan.com/2017/04/21/mt-leaf.html Twitter-Snowflake算法产生的背景相当简单,为了满足Twitter每秒上万 ...

  5. 基于AQS实现的Java并发工具类

    本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...

  6. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  7. 【SpringSecurity系列2】基于SpringSecurity实现前后端分离无状态Rest API的权限控制原理分析

    源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/01-springsecurity-state ...

  8. snowflake算法(java版)

     转自:http://www.cnblogs.com/haoxinyue/p/5208136.html 1. 数据库自增长序列或字段 最常见的方式.利用数据库,全数据库唯一. 优点: 1)简单,代码方 ...

  9. 基于Windows下处理Java错误:编码GBK的不可映射字符的解决方案

    基于Windows下处理Java错误:编码GBK的不可映射字符的解决方案 最近在研究Java,涉及命令行编译,使用notepad++编辑器,然后使用javac编译: 之前的几个文件没有中文的内容,都没 ...

随机推荐

  1. 触屏touchstart 与 click

    设计效果:当手指点击或触摸红框线menuList之外的部分时,弹框menuList消失. 问题:在优化触屏版的时候发现如图问题,当menuList弹出,手指触摸屏幕向下滑动时,menuList弹框不消 ...

  2. IndexOf、IndexOfAny 、Remove

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. 深入理解Linux修改hostname

    当我觉得对Linux系统下修改hostname已经非常熟悉的时候,今天碰到了几个个问题,这几个问题给我好好上了一课,很多知识点,当你觉得你已经掌握的时候,其实你了解的还只是皮毛.技术活,切勿浅尝则止! ...

  4. CMS本质上是什么

    2015-121.数据可以任意取和构造,结构也很自由,不一定是“站点-栏目-文章-评论”.2.主要用于显示,前台不产生数据(评论.浏览次数除外).3.在模版进行循环.判断,也比后台写代码要方便很多很多 ...

  5. MongoDB学习笔记~MongoVUE对数据进行查询,排序和按需显示

    回到目录 对于MongoDB这个非关系型数据库(NoSql)来说,找一个IDE工具不是很容易,还好被我找到了,它就是大名鼎鼎的MongoVUE,它可以对mongodb数据表进行增删改查,下面我主要说一 ...

  6. 写了一个常规性生成merge 的小脚本

    现在使用数据库来写存储过程,动不动参数就会用到xml ,当然罗,优势也很明显,参数相对固定,而且灵活,如果要修改或者什么的,中间接口层也不需要做变化,只需要修改封装的存储过程以及程序传参就ok了. 随 ...

  7. Mysql 安装-windows X64

    1.首先下载mysql文件包 2.将下载到的mysql-5.6.24-x64.zip进行解压. 3.安装,直接下一步. 4.进入文件夹内复制my-default.ini文件,并重命名为my.ini 5 ...

  8. 【转】java NIO 相关知识

    原文地址:http://www.iteye.com/magazines/132-Java-NIO Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的 ...

  9. 【转】Java并发编程:volatile关键字解析

    转自:http://www.importnew.com/18126.html#comment-487304 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备 ...

  10. 【Windows编程】系列第七篇:Menubar的创建和使用

    上一篇我们学习了利用windows API创建工具栏和菜单栏,与上一篇紧密联系的就是菜单栏,菜单栏是一个大多数复杂一些的Windows应用程序不可或缺的部分.比如下图就是Windows自带的记事本的菜 ...