分布式的Id生成器
项目中需要一个分布式的Id生成器,twitter的Snowflake中这个既简单又高效,网上找的Java版本
package com.cqfc.id; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; /**
* tweeter的snowflake 移植到Java:
* (a) id构成: 42位的时间前缀 + 10位的节点标识 + 12位的sequence避免并发的数字(12位不够用时强制得到新的时间前缀)
* 注意这里进行了小改动: snowkflake是5位的datacenter加5位的机器id; 这里变成使用10位的机器id
* (b) 对系统时间的依赖性非常强,需关闭ntp的时间同步功能。当检测到ntp时间调整后,将会拒绝分配id
*/ public class IdWorker { private final static Logger logger = LoggerFactory.getLogger(IdWorker.class); private final long workerId;
private final long epoch = 1403854494756L; // 时间起始标记点,作为基准,一般取系统的最近时间
private final long workerIdBits = 10L; // 机器标识位数
private final long maxWorkerId = -1L ^ -1L << this.workerIdBits;// 机器ID最大值: 1023
private long sequence = 0L; // 0,并发控制
private final long sequenceBits = 12L; //毫秒内自增位 private final long workerIdShift = this.sequenceBits; //
private final long timestampLeftShift = this.sequenceBits + this.workerIdBits;//
private final long sequenceMask = -1L ^ -1L << this.sequenceBits; // 4095,111111111111,12位
private long lastTimestamp = -1L; private IdWorker(long workerId) {
if (workerId > this.maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId));
}
this.workerId = workerId;
} public synchronized long nextId() throws Exception {
long timestamp = this.timeGen();
if (this.lastTimestamp == timestamp) { // 如果上一个timestamp与新产生的相等,则sequence加一(0-4095循环); 对新的timestamp,sequence从0开始
this.sequence = this.sequence + 1 & this.sequenceMask;
if (this.sequence == 0) {
timestamp = this.tilNextMillis(this.lastTimestamp);// 重新生成timestamp
}
} else {
this.sequence = 0;
} if (timestamp < this.lastTimestamp) {
logger.error(String.format("clock moved backwards.Refusing to generate id for %d milliseconds", (this.lastTimestamp - timestamp)));
throw new Exception(String.format("clock moved backwards.Refusing to generate id for %d milliseconds", (this.lastTimestamp - timestamp)));
} this.lastTimestamp = timestamp;
return timestamp - this.epoch << this.timestampLeftShift | this.workerId << this.workerIdShift | this.sequence;
} private static IdWorker flowIdWorker = new IdWorker(1);
public static IdWorker getFlowIdWorkerInstance() {
return flowIdWorker;
} /**
* 等待下一个毫秒的到来, 保证返回的毫秒数在参数lastTimestamp之后
*/
private long tilNextMillis(long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
} /**
* 获得系统当前毫秒数
*/
private static long timeGen() {
return System.currentTimeMillis();
} public static void main(String[] args) throws Exception {
System.out.println(timeGen()); IdWorker idWorker = IdWorker.getFlowIdWorkerInstance();
// System.out.println(Long.toBinaryString(idWorker.nextId()));
System.out.println(idWorker.nextId());
System.out.println(idWorker.nextId());
} }
分布式的Id生成器的更多相关文章
- 分布式全局ID生成器设计
项目是分布式的架构,需要设计一款分布式全局ID,参照了多种方案,博主最后基于snowflake的算法设计了一款自用ID生成器.具有以下优势: 保证分布式场景下生成的ID是全局唯一的 生成的全局ID整体 ...
- Jedis使用总结【pipeline】【分布式的id生成器】【分布式锁【watch】【multi】】【redis分布式】(转)
前段时间细节的了解了Jedis的使用,Jedis是redis的java版本的客户端实现.本文做个总结,主要分享如下内容: [pipeline][分布式的id生成器][分布式锁[watch][multi ...
- 分布式唯一id生成器的想法
0x01 起因 前端时间遇到一个问题,怎么快速生成唯一的id,后来采用了hashid的方法.最近在网上读到了美团关于分布式唯一id生成器的解决方案, 其中提到了三种生成法:(建议看一下这篇文章,写得很 ...
- 百度开源的分布式唯一ID生成器UidGenerator,解决了时钟回拨问题
UidGenerator是百度开源的Java语言实现,基于Snowflake算法的唯一ID生成器.而且,它非常适合虚拟环境,比如:Docker.另外,它通过消费未来时间克服了雪花算法的并发限制.Uid ...
- 分布式唯一ID生成器Twitter
分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种简单一 ...
- 分布式全局ID生成器原理剖析及非常齐全开源方案应用示例
为何需要分布式ID生成器 **本人博客网站 **IT小神 www.itxiaoshen.com **拿我们系统常用Mysql数据库来说,在之前的单体架构基本是单库结构,每个业务表的ID一般从1增,通过 ...
- snowflake 分布式唯一ID生成器
本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 原文参考运维生存和开源中国上的代码整理 我的环境是pytho ...
- 分布式唯一ID生成器
在应用程序中,经常需要全局唯一的ID作为数据库主键.如何生成全局唯一ID? 首先,需要确定全局唯一ID是整型还是字符串?如果是字符串,那么现有的UUID就完全满足需求,不需要额外的工作.缺点是字符串作 ...
- 分布式ID生成器
最近会写一篇分布式的ID生成器的文章,先占位.借鉴Mongodb的ObjectId的生成: 4byte时间戳 + 3byte机器标识 + 2byte PID + 3byte自增id 简单代码: imp ...
随机推荐
- Linux下的C Socket编程 -- 简介与client端的处理
Linux下的C Socket编程(一) 介绍 Socket是进程间通信的方式之一,是进程间的通信.这里说的进程并不一定是在同一台机器上也有可能是通过网络连接的不同机器上.只要他们之间建立起了sock ...
- hadoopfs: 未找到命令...
https://zhidao.baidu.com/question/240817305095236244.html 学习hadoop测试http://blog.csdn.net/thinkpadshi ...
- 跨应用使用Spoon框架截图的方法
spoon框架是一个很棒的用例驱动跟测试结果生成加工的框架.但在使用spoon-client时,传入参数需要被测应用的activity实例,跨应用测试会很受限(当然也可能是因为我对android不熟导 ...
- Django rest_framework 实用技巧
前言: 最近工作中需要用到Django rest_framework框架做API, 边学边写,记录了一些实际工作中需要用到的功能,不是很全也不系统,以后需要什么功能可以在这查询. 后续还会更新其它的用 ...
- [LeetCode] Convert a Number to Hexadecimal 数字转为十六进制
Given an integer, write an algorithm to convert it to hexadecimal. For negative integer, two’s compl ...
- 将HTML5封装成android应用APK文件的几种方法
越来越多的开发者热衷于使用html5+JavaScript开发移动Web App.不过,HTML5 Web APP的出现能否在未来取代移动应用,就目前来说,还是个未知数.一方面,用户在使用习惯上,不喜 ...
- weui 搜索框
点击搜索,会显示关键字取消按钮,输入文字,会在搜索框下,有相应的列表显示. HTML: <!DOCTYPE html> <html> <head> <meta ...
- 【BZOJ-2938】病毒 Trie图 + 拓扑排序
2938: [Poi2000]病毒 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 609 Solved: 318[Submit][Status][Di ...
- 【BZOJ-3143】游走 高斯消元 + 概率期望
3143: [Hnoi2013]游走 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2264 Solved: 987[Submit][Status] ...
- 【gulp】工作中的实战
写这篇文章的目的是为了以后的项目中懒得再去配gulp,直接可以拿这篇博客中的来用,因为有时候配置还是挺烦人的. gulp相关插件的介绍 用法比较简单,假设大家都会用gulp,下面主要介绍一下一些插件的 ...