分布式ID生成器

目前微服务架构盛行,在分布式系统中的操作中都会有一些全局性ID的需求,所以我们不能使用数据库本身的自增
功能来产生主键值,只能由程序来生成唯一的主键值。我们采用的是开源的twitter( 非官方中文惯称:推特.是国外
的一个网站,是一个社交网络及微博客服务) 的snowflake (雪花)算法。

各个段解析:

分段 作用 说明
1bit 保留(不用) ---
41bit 时间戳,精确到毫秒 最多可以支持69年的跨度
5bit 机器id 最多支持2的5次方(32)个节点
5bit 业务编码 最多支持2的5次方(32)个节点
12bit 毫秒内的计数器 每个节点每毫秒最多产生2的12次方(4096)个id

默认情况下41bit的时间戳可以支持该算法使用到2082年,10bit的工作机器id可以支持1024台机器,序列号
支持1毫秒产生4096个自增序列id . SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内
不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID
左右

package com.hrm.common.utils;import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.NetworkInterface;//雪花算法代码实现
public class IdWorker {// 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动)private final static long twepoch = 1288834974657L;// 机器标识位数private final static long workerIdBits = 5L;// 数据中心标识位数private final static long datacenterIdBits = 5L;// 机器ID最大值private final static long maxWorkerId = -1L ^ (-1L << workerIdBits);// 数据中心ID最大值private final static long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);// 毫秒内自增位private final static long sequenceBits = 12L;// 机器ID偏左移12位private final static long workerIdShift = sequenceBits;// 数据中心ID左移17位private final static long datacenterIdShift = sequenceBits + workerIdBits;// 时间毫秒左移22位private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;private final static long sequenceMask = -1L ^ (-1L << sequenceBits);/* 上次生产id时间戳 */private static long lastTimestamp = -1L;// 0,并发控制private long sequence = 0L;private final long workerId;// 数据标识id部分private final long datacenterId;public IdWorker(){this.datacenterId = getDatacenterId(maxDatacenterId);this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);}/*** @param workerId*            工作机器ID* @param datacenterId*            序列号*/public IdWorker(long workerId, long datacenterId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}this.workerId = workerId;this.datacenterId = datacenterId;}/*** 获取下一个ID** @return*/public synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {// 当前毫秒内,则+1sequence = (sequence + 1) & sequenceMask;if (sequence == 0) {// 当前毫秒内计数满了,则等待下一秒timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;// ID偏移组合生成最终的ID,并返回IDlong nextId = ((timestamp - twepoch) << timestampLeftShift)| (datacenterId << datacenterIdShift)| (workerId << workerIdShift) | sequence;return nextId;}private long tilNextMillis(final long lastTimestamp) {long timestamp = this.timeGen();while (timestamp <= lastTimestamp) {timestamp = this.timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}/*** <p>* 获取 maxWorkerId* </p>*/protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {StringBuffer mpid = new StringBuffer();mpid.append(datacenterId);String name = ManagementFactory.getRuntimeMXBean().getName();if (!name.isEmpty()) {/** GET jvmPid*/mpid.append(name.split("@")[0]);}/** MAC + PID 的 hashcode 获取16个低位*/return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);}/*** <p>* 数据标识id部分* </p>*/protected static long getDatacenterId(long maxDatacenterId) {long id = 0L;try {InetAddress ip = InetAddress.getLocalHost();NetworkInterface network = NetworkInterface.getByInetAddress(ip);if (network == null) {id = 1L;} else {byte[] mac = network.getHardwareAddress();id = ((0x000000FF & (long) mac[mac.length - 1])| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;id = id % (maxDatacenterId + 1);}} catch (Exception e) {System.out.println(" getDatacenterId: " + e.getMessage());}return id;}
}

工程搭建:搭建子工程之分布式id生成器相关推荐

  1. Qt把已有工程添加到其他工程中作为子工程或新创建子工程

    Qt创建子工程 新建一个空工程 添加子工程 在当前工程下添加一个子工程 一个已有的qt工程,想添加到其他工程作为一个子工程,或是在当前工程中添加一个子工程,可以使用以下方法. 假设已有的工程为test ...

  2. 融云发送图片消息_IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现...

    1.引言 很多人一想到IM应用开发,第一印象就是"长连接"."socket"."保活"."协议"这些关键词,没错,这些确 ...

  3. IM消息ID技术专题(五):开源分布式ID生成器UidGenerator的技术实现

    1.引言 很多人一想到IM应用开发,第一印象就是"长连接"."socket"."保活"."协议"这些关键词,没错,这些确 ...

  4. 来吧,自己动手撸一个分布式ID生成器组件

    在经过了众多轮的面试之后,小林终于进入到了一家互联网公司的基础架构组,小林目前在公司有使用到架构组研究到分布式id生成器,前一阵子大概看了下其内部的实现,发现还是存在一些架构设计不合理之处.但是又由于 ...

  5. 美团(Leaf)分布式ID生成器,好用的一批!

    不了解分布式ID的同学,先行去看<一口气说出 9种 分布式ID生成方式,面试官有点懵了>温习一下基础知识,这里就不再赘述了 美团(Leaf) Leaf是美团推出的一个分布式ID生成服务,名 ...

  6. c#分布式ID生成器

    c#分布式ID生成器 简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余63 ...

  7. 分布式ID生成器的解决方案总结

    转载自 分布式ID生成器的解决方案总结 在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID.退款ID等.那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们 ...

  8. java redis id生成器_基于redis的分布式ID生成器

    项目地址 基于redis的分布式ID生成器. 准备 首先,要知道redis的EVAL,EVALSHA命令: 原理 利用redis的lua脚本执行功能,在每个节点上通过lua脚本生成唯一ID. 生成的I ...

  9. 分布式id生成器:彻底解决雪花算法时间回拨问题

    Butterfly 简介 雪花算法是twitter提出的分布式id生成器方案,但是有三个问题,其中前两个问题在业内很常见: 时间回拨问题 机器id的分配和回收问题 机器id的上限问题 Butterfl ...

最新文章

  1. eeglab教程系列(10)-绘制ERP图像
  2. Mybatis主要内容
  3. Linux设备管理(三):sysfs文件系统的功能及其应用
  4. assert()理解
  5. svn汉化依然失败无解
  6. 淘宝,京东,苏宁易购技术架构(路线)分析和比较
  7. 第三章 高频谐振功率放大器(关键点:功率、效率)
  8. 8.用C/C++实现一个科学计算器———(超级详细完整,包含C/C++版本和Qt版本)
  9. 靠写iPhone程序发财的三个故事
  10. C#操作开机自启动(写进注册表)
  11. Java图形用户界面设计音乐播放器
  12. WordPress 衍生产品 BuddyPress 年底发布
  13. 关于xamarin汉字转换成拼音
  14. 论文导读:A Diversity-Promoting Objective Function for Neural Conversation Models
  15. 条码打印软件之如何在条码内容插入字符而不被扫描
  16. 2019华为软件精英挑战赛赛后总结
  17. win8 激活历程 真激活与假激活
  18. WIN10 3个手指拖动_老树谷歌地图数据采集大师下载-谷歌地图数据采集 v1.3.0.3 官方版...
  19. 【2019CVPR学习】翻译-Graph Attention Convolution for Point Cloud Semantic Segmentation
  20. 教女朋友学Python

热门文章

  1. Instr()函数用法
  2. 获取指定某一天的00:00—23:59
  3. 【Java线程】线程同步—synchronized Lock
  4. 记录一次dubbo项目实战
  5. UVA10474 Where is the Marble?
  6. 搭建本地的git仓库
  7. 第 十 一 天 : 复 习 完 ( 四 )
  8. 视频:参加ZDNet《小崔说事》谈知识管理
  9. Spring quartz 并发性研究
  10. 用java做出两行三列的表格_Java中,使用HSSFSheet创建excel模板如何创建一列两行的数据?...