前言"在分布式系统中常见的问题就是如何生成流水号,一般情况下会有专门的流水号系统,不过在开发过程中或者开发早期不一定会有专门流水号系统,在这里介绍下我所使用的流水号生成器——雪花算法"

  1  

概述

雪花算法生成的ID结果是一个64bit大小的整数,并且保证在分布式系统中不会重复。

结构

使用64位long型数字作为全局唯一id

1位 无意义 0

41位 时间戳

5位 机房id

5位 机器id

12位自增序号 表示同一时间同一机房同一机器生成的序列号

1. 1位为什么没有意义?

二进制中 第一位代表符号位, 默认 0 表示生成的序列号为正数

2. 41位时间戳

41位最大能表示 2^41-1 的数字,毫秒值 69.7年。

(2^41-1)/1000/60/60/24

当时间大于69.7即时间戳差值大于 2199023255551,会开始出现负值流水号

3. 机房id+机器id

机房id+机器id 2^10 1024台机器。

// 但是使用中不可能每部署一台机器都改下编号, 所以我做出以下改动// 8位机器号(最大256) 2位机房号// 机器号使用IP地址后三位 机房id 默认1// 只需要确保机器的ip后三位不同即可private static final long MACHINE_BIT = 8;private static final long DATA_CENTER_BIT = 2;

private static final long DATA_CENTER_ID = 1;private static long address;static {    InetAddress localIp = IpUtils.getLocalIp();    address = localIp.getAddress()[3] & 0xff;    log.info("当前系统的 address 为: {}", address);}

4. 12位序列号

表示同一毫秒内生成的id 2^12-1 个正整数。

总结

SnowFlake每秒能够产生26万ID左右

优点:

生成ID时不依赖于DB,完全在内存生成,高性能高可用。ID呈趋势递增,后续插入索引树的时候性能较好。

缺点:

依赖于系统时钟的一致性。如果某台机器的系统时钟回拨,有可能造成ID冲突,或者ID乱序。

  2  

代码SerialNumber

public class SerialNumber  {

    /**     * 起始的时间戳 2018-01-01 00:00:00     */    private static final long START_STAMP = 1514736000000L;

    /**     * 每一部分占用的位数     * 序列号 占用位数 12 位 (同一毫秒内生成的id 2^12-1 个正整数)     * 机器标识  占用位数 8 位 (一般是使用5位)     * 数据中心 占用位数 2 位 (一般是使用5位)     *     */    private static final long SEQUENCE_BIT = 12;    private static final long MACHINE_BIT = 8;    private static final long DATA_CENTER_BIT = 2;

    /**     * 每一部分的最大值     */    private static final long MAX_DATA_CENTER_NUM = ~(-1L <    private static final long MAX_MACHINE_NUM = ~(-1L <    private static final long MAX_SEQUENCE = ~(-1L <    /**     * 每一部分向左的位移     * 机器Id左移12位 (SEQUENCE_BIT = 12)     * 数据中心左移20位 (SEQUENCE_BIT + MACHINE_BIT = 12 + 8)     * 时间戳左移22位 (DATA_CENTER_LEFT + DATA_CENTER_BIT = 12 + 8 + 2)     *     */    private static final long MACHINE_LEFT = SEQUENCE_BIT;    private static final long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;    private static final long TIME_STAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;    /**     * 数据中心 机器标识 序列号 上一次时间戳     * 数据中心标识和机器标识一般是外部传入     */    private static final long DATA_CENTER_ID = 1;    private static long address;    private long sequence = 0L;    private long lastStamp = -1L;

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");

    static {      InetAddress localIp = IpUtils.getLocalIp();      address = localIp.getAddress()[3] & 0xff;      log.info("当前系统的 address 为: {}", address);    }

    /**     * 产生下一个ID     *     * @return     */    private synchronized long nextId() {        long currStamp = getNewStamp();        if (currStamp             throw new RuntimeException("Clock moved backwards.  Refusing to generate id");        }

        if (currStamp == lastStamp) {            // 相同毫秒内,序列号自增 (sequence + 1) & (~(-1L <            sequence = (sequence + 1) & MAX_SEQUENCE;// 同一毫秒的序列数已经达到最大if (sequence == 0L) {                currStamp = getNextMill();            }        } else {// 不同毫秒内,序列号置为0            sequence = 0L;        }        lastStamp = currStamp;// 时间戳部分 数据中心部分 机器标识部分 序列号部分return (currStamp - START_STAMP) <            | address <    }private long getNextMill() {long mill = getNewStamp();while (mill <= lastStamp) {            mill = getNewStamp();        }return mill;    }private long getNewStamp() {return System.currentTimeMillis();    }}

IpUtils

import java.net.*;import java.util.Enumeration;

/** * @author liuzhihang * @date 2019/12/19 16:03 */public class IpUtils {

    public static InetAddress getLocalIp() {        try {            for (Enumeration e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements(); ) {                NetworkInterface item = e.nextElement();for (InterfaceAddress address : item.getInterfaceAddresses()) {if (item.isLoopback() || !item.isUp()) {continue;                    }if (address.getAddress() instanceof Inet4Address) {return address.getAddress();                    }                }            }return InetAddress.getLocalHost();        } catch (SocketException | UnknownHostException e) {throw new RuntimeException(e);        }    }}

- -


作者:刘志航,一个宅宅的北漂程序员。

" 阅读源码,记录笔记;享受生活,分享心得。"

觉得好看就点个在看吧 

根据时间戳生成编号_使用雪花算法生成流水号!相关推荐

  1. 雪花算法及运用PHP,雪花算法生成全局唯一ID,参考了下网上雪花算法生成规则,机器ID和序列号自动获取 理论上毫秒可生成 1024*4096个唯一ID

    任务要求毫秒生成10000个唯一ID 研究了下twitter/snowflake的算法思想: 参考了下网上雪花算法生成规则,把数据中心和机器编号整合一起,变成10位机器ID, 机器ID和序列号自动获取 ...

  2. 基于雪花算法生成用户id

    8.1 为啥这样做 1.全局唯一性,不会出现重复的id.如果通过id自增来保证id不重复,则该表 无法分表操作例如 服务器A的数据库的user表 数据如下1 小明 男2 小红 女2 张三 男此时 进行 ...

  3. 线上使用雪花算法生成id重复问题

    项目中使用的是hutool工具类库提供的雪花算法生成id方式,版本使用的是5.3.1 <dependency><groupId>cn.hutool</groupId> ...

  4. mybatis-plus雪花算法生成Id使用详解

    文章目录 前言 一.mybatis-plus官网 二.雪花算法实战 1.建表 2.新建测试工程 3.单元测试 三.实现分析 四.为什么默认就是雪花算法 五.主动设置Id生成策略 六.内置的雪花算法工具 ...

  5. DefaultIdentifierGenerator 雪花算法 生成 重复 id 解决办法

    DefaultIdentifierGenerator 雪花算法 生成 重复 id 前言 问题发生 排查原因 问题解决 前言 利用 mybatisplus 的 DefaultIdentifierGene ...

  6. 雪花算法生成分布式ID的时间回拨问题处理

    一般方法 1.直接抛异常 2.延迟等待到最新时间(需要回拨时间比较短) 3.采用历史最大时间 package com.zjq.javabasic.algorithm;/*** @description ...

  7. Java工具类--雪花算法生成全局唯一ID

    import java.lang.management.ManagementFactory; import java.net.InetAddress; import java.net.NetworkI ...

  8. python雪花算法生成id_理解分布式id生成算法SnowFlake

    分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种. 概述 SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 1位,不用.二进制中最高位 ...

  9. SpringBoot 雪花算法生成商品订单号【SpringBoot系列13】

    SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见. 程序员每天的CV 与 板砖,也要知其所以然,本系列课程可以帮助初学者学习 SpringBooot 项目开发 与 SpringCl ...

最新文章

  1. php mysql table_关于php:MySQL Table不存在错误,但确实存在
  2. 软件工程硕士和计算机硕士论文题目,计算机硕士毕业论文答辩自述
  3. python并发编程之多线程理论部分
  4. 抛硬币正面期望_如果抛硬币,正面的数量多于反面的可能性
  5. 10kv线路负载率计算_10kV配电线路保护的整定计算
  6. 【拾贝】hive unoin all map数爆增
  7. python数据存储系列教程——python(pandas)读写csv文件
  8. 通过外挂插件向预训练语言模型中融入知识
  9. 利用js解析php的表单数据
  10. 想成为优秀的技术人员你必须做到的几件事情【转载】
  11. 如何把pdf文件转换为excel表格
  12. 音乐播放类应用后台播放耗电评测报告 1
  13. Linux 之 vim 使用
  14. 100万“音乐难民”陪伴虾米到最后一刻
  15. 计算机之父—— 约翰·冯·诺依曼
  16. vue关闭eslint语法检查
  17. 用css的animation动画属性来实现一个H5场景动态电子邀请函
  18. R网格MIC与频繁项集
  19. (转)Windows 7 系统下载安装一贴导航
  20. springboot项目:老年教育学习系统fte91(java+VUE+Mybatis+Maven+Mysql)

热门文章

  1. 我对无服务器架构的一些看法
  2. 在 Linux shell 中自由操作时间变量
  3. 【ActiveReports 大数据分析报告】用数据分析的手段告诉你,复联4有多火爆?
  4. 关于数论【莫比乌斯反演】
  5. 数据库的相关语句(where,order by)
  6. javascript里的几种常见的数组方法
  7. js部分---表单验证;(含正则表达式)
  8. 终于下定决心以后要定期清理清理一下园子啦
  9. C# 程序Hello World
  10. 「2012-12-29」3x3手机锁屏矩阵图像的组合数量