/**
* ID生成 雪花算法
*/
public class SnowFlake
{
public static SnowFlake getInstance()
{
return SingletonSnowFlake.instance;
} private static class SingletonSnowFlake
{
private static final SnowFlake instance = new SnowFlake(1,1);
} /**
* 起始的时间戳
*/
private final static long START_STMP = 1480166465631L; /**
* 每一部分占用的位数
*/
private final static long SEQUENCE_BIT = 12; //序列号占用的位数 private final static long MACHINE_BIT = 5; //机器标识占用的位数 private final static long DATACENTER_BIT = 5;//数据中心占用的位数 /**
* 每一部分的最大值
*/
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT); private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT); private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT); /**
* 每一部分向左的位移
*/
private final static long MACHINE_LEFT = SEQUENCE_BIT; private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; private long datacenterId; //数据中心 private long machineId; //机器标识 private long sequence = 0L; //序列号 private long lastStmp = -1L;//上一次时间戳 public SnowFlake(long datacenterId, long machineId)
{
if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0)
{
throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
} if (machineId > MAX_MACHINE_NUM || machineId < 0)
{
throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
} this.datacenterId = datacenterId; this.machineId = machineId;
} /**
* 产生下一个ID
*
* @return
*/
public synchronized long nextId()
{ long currStmp = getNewstmp(); if (currStmp < lastStmp)
{
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
} if (currStmp == lastStmp)
{
//相同毫秒内,序列号自增
sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列数已经达到最大
if (sequence == 0L)
{
currStmp = getNextMill();
}
}
else
{
//不同毫秒内,序列号置为0
sequence = 0L;
} lastStmp = currStmp; return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分
| datacenterId << DATACENTER_LEFT //数据中心部分
| machineId << MACHINE_LEFT //机器标识部分
| sequence; //序列号部分
} private long getNextMill()
{
long mill = getNewstmp(); while (mill <= lastStmp)
{
mill = getNewstmp();
}
return mill;
} private long getNewstmp()
{
return System.currentTimeMillis();
} public static void main(String[] args)
{
SnowFlake snowFlake = new SnowFlake(1, 1); long start = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++)
{
System.out.println(snowFlake.nextId());
} System.out.println(System.currentTimeMillis() - start); }
}

ID生成 雪花算法的更多相关文章

  1. 全局ID生成--雪花算法

    分布式ID常见生成策略: 分布式ID生成策略常见的有如下几种: 数据库自增ID. UUID生成. Redis的原子自增方式. 数据库水平拆分,设置初始值和相同的自增步长. 批量申请自增ID. 雪花算法 ...

  2. 分布式ID生成 - 雪花算法

    雪花算法是一种生成分布式全局唯一ID的经典算法,关于雪花算法的解读网上多如牛毛,大多抄来抄去,这里请参考耕耘的小象大神的博客ID生成器,Twitter的雪花算法(Java) 网上的教程一般存在两个问题 ...

  3. 全局ID生成--雪花算法改进版

    存在的问题 时间回拨问题:由于机器的时间是动态的调整的,有可能会出现时间跑到之前几毫秒,如果这个时候获取到了这种时间,则会出现数据重复 机器id分配及回收问题:目前机器id需要每台机器不一样,这样的方 ...

  4. ID 生成器 雪花算法

    https://blog.csdn.net/wangming520liwei/article/details/80843248 ID 生成器 雪花算法 2018年06月28日 14:58:43 wan ...

  5. 分布式ID的雪花算法及坑

    分布式ID生成是目前系统的常见刚需,其中以Twitter的雪花算法(Snowflake)比较知名,有Java等各种语言的版本及各种改进版本,能生成满足分布式ID,返回ID为Long长整数 但是这里有一 ...

  6. 适用于分布式ID的雪花算法

    基于Java实现的适用于分布式ID的雪花算法工具类,这里存一下日后好找 /** * 雪花算法生成ID */ public class SnowFlakeUtil { private final sta ...

  7. 分布式系统-主键唯一id,订单编号生成-雪花算法-SnowFlake

    分布式系统下 我们每台设备(分布式系统-独立的应用空间-或者docker环境) * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作 ...

  8. 全局唯一iD的生成 雪花算法详解及其他用法

    一.介绍 雪花算法的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等. 自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景.GUID:采用无意义字符串,数据量增大时造成 ...

  9. 生成主键ID,唯一键id,分布式ID生成器雪花算法代码实现

    工具类:  package com.ihrm.common.utils; import java.lang.management.ManagementFactory; import java.net. ...

随机推荐

  1. 【DP 好题】hihoCoder #1520 古老数字

    题目链接 这道题的要点是状态转移的顺序. 要从低位向高位进行状态转移. Implementation string s; cin >> s; reverse(all(s)); int x, ...

  2. Python 入门 之 类的三大关系(依赖 / 组合/ 继承关系)

    Python 入门 之 类的三大关系(依赖 / 组合/ 继承关系) 在面向对象的中,类与类之间存在三种关系:依赖关系.组合关系.继承关系. 1.依赖关系:将一个类的类名或对象当做参数传递给另一个函数被 ...

  3. 引入DDT

    一.大致介绍: DDT-Data Driven Test 是Python的第三方库,提供了创建数据驱动的测试,在线安装为:pip install ddt @data 表示元祖的列表数据 @unpack ...

  4. (转)Redis持久化的几种方式

    radis持久化的几种方式 1.前言 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服 ...

  5. gitlab操作笔记

    基本命令 准备 1. 安装所需命令 sudo yum install curl openssh-server openssh-clients postfix cronie -y2. 安装SSH sud ...

  6. luogu P4437 [HNOI/AHOI2018]排列

    luogu 问题本质是把\(a_i\)作为\(i\)的父亲,然后如果有环就不合法,否则每次要取数,要满足取之前他的父亲都被取过(父亲为0可以直接取),求最大价值 贪心想法显然是要把权值大的尽量放在后面 ...

  7. 关于redis的几件小事(一)redis的使用目的与问题

    1.redis是用来干嘛的? Redis is an open source (BSD licensed), in-memory data structure store, used as a dat ...

  8. 帝国cms 通过文章的id获取信息

    获取栏目id为13下id为46的数据 [e:loop={"select * from phome_ecms_news where classid = 13 and id = 46" ...

  9. 两种表复制语句(SQL)

    select into select语句和select into from语句 1.INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field ...

  10. python3 调用zabbix API实现批量增加删除主机,主机各种监控项------实战

    在以前的博客中谈到了利用zabbix接口来对主机进行批量的增删改查 这里在不用环境中实战遇到了不同问题,这里记录下来以便后续review 以下为实战中获取token的代码,在zabbix标准接口文档中 ...