精华内容
下载资源
问答
  • /** * * Twitter 的分布式自增 ID 雪花算法 snowflake (Java版) * * * @author:bood * @date:2020/10/16 */ public class SnowFlake { /** * 起始的时间戳 */ private final static long START_STMP = ...
    package org.bood.common.utils;
    
    /**
     * <p>
     * Twitter 的分布式自增 ID 雪花算法 snowflake (Java版)
     * </p>
     * 
     * @author:bood
     * @date:2020/10/16
     */
    public class SnowFlake {
    
        /**
         * 起始的时间戳
         */
        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() {
        }
    
        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;
        }
    
        /**
         * <p>
         * 产生下一个ID
         * </p>
         *
         * @return:long
         * @author:bood
         * @date:2020/10/16
         */
        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(2, 3);
    
            long start = System.currentTimeMillis();
            for (int i = 0; i < 100; i++) {
                System.out.println(snowFlake.nextId());
            }
    
            System.out.println(System.currentTimeMillis() - start);
        }
    
    }
    

    在这里插入图片描述

    展开全文
  • Twitter的分布式自增ID雪花算法snowflake (Java版)
  • * 描述: Twitter的分布式自增ID雪花算法snowflake (Java版) * https://github.com/souyunku/SnowFlake * * @author yanpenglei * @create 2018-03-13 12:37 **/ public class SnowFlake { /** * 起...

    非原创,转载

     

    /**
     * 描述: Twitter的分布式自增ID雪花算法snowflake (Java版)
     * https://github.com/souyunku/SnowFlake
     *
     * @author yanpenglei
     * @create 2018-03-13 12:37
     **/
    public class SnowFlake {

        /**
         * 起始的时间戳
         */
        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(2, 3);

            long start = System.currentTimeMillis();
            for (int i = 0; i < 1000000; i++) {
                System.out.println(snowFlake.nextId());
            }

            System.out.println(System.currentTimeMillis() - start);


        }
    }

    展开全文
  • package ... /** /** * Biz-Boot, All rights reserved * 版权:企业之家网 -- 企业建站管理系统<br/> ...br/>... * 描述: Twitter的分布式自增ID雪花算法snowflake (Java版) * * @au...
    package com.flycms.common.utils.mark; /**
    
    /**
     * Biz-Boot, All rights reserved
     * 版权:企业之家网 -- 企业建站管理系统<br/>
     * 开发公司:97560.com<br/>
     *
     * 描述: Twitter的分布式自增ID雪花算法snowflake (Java版)
     *
     * @author 孙开飞
     * @create 2018-08-13 12:37
     **/
    public class SnowFlakeUtils {
    
        /**
         * 起始的时间戳
         */
        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 static long datacenterId;  //数据中心
        private static long machineId;     //机器标识
        private static long sequence = 0L; //序列号
        private static long lastStmp = -1L;//上一次时间戳
    
        public SnowFlakeUtils(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 static 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 static long getNextMill() {
            long mill = getNewstmp();
            while (mill <= lastStmp) {
                mill = getNewstmp();
            }
            return mill;
        }
        private static long getNewstmp() {
            return System.currentTimeMillis();
        }
        public static void main(String[] args) {
            SnowFlakeUtils snowFlake = new SnowFlakeUtils(2, 3);
            long start = System.currentTimeMillis();
            for(int i=0; i < 50;i++){
                System.out.println(snowFlake.nextId());
            }
            System.out.println(System.currentTimeMillis() - start);
        }
    }
    
    
    展开全文
  • * 描述: Twitter的分布式自增ID雪花算法snowflake (Java版) * * @create 2018-03-13 12:37 **/ public class SnowFlake { public static Long mac ; public static Long ip ; /** *...

    目的:在高并发场景下实现不重复的id值


    1.在mysql数据库中,主键为自增,但在高并发分布式场景下,需要在自增字段的基础上加上机器码等特征码,用来区分id

    启动顺序:eureka–>saasplatform-common–>saasplatform-coupon-war-core
    在chitai-public的IDeploy中配置数据库生成自增id的配置,初始值设为1

    注意:没有配置则会报错:
    在这里插入图片描述
    解决办法:
    在指定位置创建两个文件,设置初始值都是1


    2.雪花算法代码:(生成64位长度18的id)

    • 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
    • 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
    • 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
    • 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
    • 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号

      加起来刚好64位,为一个Long型。
    package com.chitai.saasplatform.base.util;
    
    
    import org.apache.commons.lang3.RandomUtils;
    import org.apache.commons.lang3.StringUtils;
    
    
    import java.net.*;
    import java.util.Enumeration;
    
    
    /**
     * 描述: Twitter的分布式自增ID雪花算法snowflake (Java版)
     *
     * @create 2018-03-13 12:37
     **/
    
    public class SnowFlake {
    
        public static Long mac;
        public static Long ip;
    
    
        /**
         * 开始时间截 (2015-01-01)
         */
        private final static long twepoch = 1420041600000L;
    
        /**
         * 机器id所占的位数
         */
        private final static long workerIdBits = 5L;
    
        /**
         * 数据标识id所占的位数
         */
        private final static long datacenterIdBits = 5L;
    
        /**
         * 序列在id中占的位数
         */
        private final static long sequenceBits = 12L;
    
        /**
         * 机器ID向左移12位
         */
        private final static long workerIdShift = sequenceBits;
    
        /**
         * 数据标识id向左移17位(12+5)
         */
        private final static long datacenterIdShift = sequenceBits + workerIdBits;
    
        /**
         * 时间截向左移22位(5+5+12)
         */
        private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    
        /**
         * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
         */
        private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
    
        /**
         * 毫秒内序列(0~4095)
         */
        private static long sequence = 0L;
    
        /**
         * 上次生成ID的时间截
         */
        private static long lastTimestamp = -1L;
    
        /**
         * 获得下一个ID (该方法是线程安全的)
         *
         * @return SnowflakeId
         */
        private static synchronized long nextId() {
            long timestamp = timeGen();
    
            // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
            if (timestamp < lastTimestamp) {
                throw new RuntimeException(String.format(
                        "Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
            }
    
            // 如果是同一时间生成的,则进行毫秒内序列
            if (lastTimestamp == timestamp) {
                sequence = (sequence + 1) & sequenceMask;
                // 毫秒内序列溢出
                if (sequence == 0) {
                    // 阻塞到下一个毫秒,获得新的时间戳
                    timestamp = tilNextMillis(lastTimestamp);
                }
            }
            // 时间戳改变,毫秒内序列重置
            else {
                sequence = 0L;
            }
    
            // 上次生成ID的时间截
            lastTimestamp = timestamp;
    
            if (mac == null) {
                mac = getMac();
            }
            if (ip == null) {
                ip = getIp();
            }
            // 移位并通过或运算拼到一起组成64位的ID
            return ((timestamp - twepoch) << timestampLeftShift) //
                    | (mac << datacenterIdShift) //
                    | (ip << workerIdShift) //
                    | sequence;
        }
    
        /**
         * 阻塞到下一个毫秒,直到获得新的时间戳
         *
         * @param lastTimestamp 上次生成ID的时间截
         * @return 当前时间戳
         */
        protected static long tilNextMillis(long lastTimestamp) {
            long timestamp = timeGen();
            while (timestamp <= lastTimestamp) {
                timestamp = timeGen();
            }
            return timestamp;
        }
    
        /**
         * 返回以毫秒为单位的当前时间
         *
         * @return 当前时间(毫秒)
         */
        protected static long timeGen() {
            return System.currentTimeMillis();
        }
    
    
        public static Long getMac() {
            try {
                NetworkInterface net=null;
                Enumeration Interfaces = NetworkInterface.getNetworkInterfaces();
                while(Interfaces.hasMoreElements())
                {
                    NetworkInterface Interface = (NetworkInterface)Interfaces.nextElement();
                    Interface.getHardwareAddress();
                    if (Interface.getHardwareAddress()!=null){
    //                    System.out.println(Interface.getHardwareAddress());
                        net=Interface;
                        break;
                    }
                }
                byte[] macBytes = net.getHardwareAddress();
                int sum = 0;
                for (int b : macBytes) {
                    sum += Math.abs(b);
                }
                return (long) (sum % 32);
            } catch (Exception e) {
                e.printStackTrace();
                return RandomUtils.nextLong(0, 31);
            }
    
        }
    
        public static Long getIp() {
            try {
                String hostAddress = Inet4Address.getLocalHost().getHostAddress();
                int[] ints = StringUtils.toCodePoints(hostAddress);
                int sums = 0;
                for (int b : ints) {
                    sums += b;
                }
                return (long) (sums % 32);
            } catch (UnknownHostException e) {
                e.printStackTrace();
                // 如果获取失败,则使用随机数备用
                return RandomUtils.nextLong(0, 31);
            }
    
        }
    
        public static String getNextId() {
            return nextId() + String.format("%02d", System.nanoTime() % 100);
        }
    
        public static void main(String[] args) {
            for (int i = 0; i < 100; i++) {
    
                System.out.println(SnowFlake.getNextId());
            }
    
        }
    
    
    }
    
    展开全文
  • 雪花的结构如下(每部分用-分开): 概述 分布式系统中,有一些需要使用唯一的ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。 有些时候我们...
  • 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。 有些时候我们希望能使用一种简单一些的ID,并且希望ID...
  • 通过在 生产生活中,分布式的系统以及大数据量的存储和读取都离不开 ID的 唯一性,例如订单号,快递单号,商品编号等等。通常我们都会采用 uuid ,mysql replace into , 一、 UUID 直接使用 java 代码 本地生成,...
  • Uuid、数据库自增雪花算法、基于redis自研等数据库唯一ID生成策略对比 使用环境 分布式、高并发下全局唯一,趋势递增,效率高,控制并发 先直接上个对比图吧,下面大量干货警告 一、Uuid(java1.5后自带生成工具...
  • /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */ private final long maxWorkerId = -1L ^ (-1L ); /** 支持的最大数据标识id,结果是31 */ private ...
  • 雪花ID 数据库的自增主键: 从大学做实验开始就一直用自增主键,以前也没考虑过用自增主键有啥问题,直到工作后… (1)首先自增主键不适用于分库分表情况,在做数据集合的时候会出现主键重复问题,做多个系统的数据...
  • 在数据库主键设计上,比较常见的方法是采用自增ID(1开始,每次加1)和生成GUID。 数据库自增主键保证唯一性,但在分布式系统中,部署需要考虑的因素太多;GUID设计简单,能保证主键的唯一性,分布式系统中,数据库...
  • 总结起来,如果业务量小,推荐采用自增ID,如果业务量大,推荐采用雪花算法生成的随机ID。 一、摘要 在日常开发中,数据库中主键id的生成方案,主要有三种 数据库自增ID 采用随机数生成不重复的ID ...
  • 文章目录前言UUID雪花ID雪花ID生成类测试自动递增重新计数测试自增Id的好处自增Id的坏处总结 前言 那些个公众号天天推来推去就几篇剩饭文章,直接实操测试一下。 单元测试:SpringBootTest /* * 使用STS创建的...
  • 分布式系统中,有一些需要使用全局唯一 ID 的场景,这种时候为了防止ID冲突可以使用36位的通用唯一识别码/UUID(Universally Unique Identifier),但是 UUID 有一些缺点,首先他相对比较长,另外 UUID 一般是无序的...
  • Twitter的雪花算法(snowflake)自增ID

    千次阅读 2018-08-08 15:34:45
     这个最简单的方案是,数据库自增ID。为啥不用咧?有这么几点原因,一是,会依赖于数据库的具体实现,比如,mysql有自增,oracle没有,得用序列,mongo似乎也没有他自己有个什么ID,sqlserv...
  • 1、静态内部类实现的单例模式 2、初始化时通过获取系统的mac和ip作为机器id和数据标识id,不需要额外指定
  • 而twitter的snowflake(雪花算法)解决了这种需求,最初Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序ID生成机制,所以开发了这样一套全局唯一ID生成服务。 snowflake结构 首位未使用,接下来的...
  • Twitter 的分布式雪花算法 Snowflake,经测试 Snowflake 每秒能够产生 26 万个自增可排序的ID twitter 的 Snowflake 生 成ID能够按照时间有序生成 Snowflake 算法生成 id 的结果是一 个 64bit 大小的整数, 为一个 ...
  • 自增主键之雪花算法

    2019-10-29 08:32:36
    package ... /** * Twitter的分布式自增ID雪花算法snowflake **/ public class SnowFlake { /** * 起始的时间戳 */ private final static long START_STMP =...
  • 雪花算法:构建分布式自增id

    千次阅读 2018-10-29 09:22:27
    目录 一、订单id的特殊性 ...那么这种情况下, 要保证id的唯一,就不能靠数据库自增,而是自己来实现算法,生成唯一id。 二、雪花算法 这里的订单id是通过一个工具类生成的: 而工具类所采用的生成id算...
  • Twitter的分布式自增ID算法snowflake (Java版)。
  • random,雪花id,想对比自增id在mysql中要用哪个呢,本文可以指引一个方向给大家,直接上数据. 可以看出在数据量100W左右的时候,uuid的插入效率垫底,并且在后序增加了130W的数据,uudi的时间又直线下降。时间占用量...
  • Twitter的分布式雪花算法SnowFlake,经测试snowflake每秒能够产生26万个自增可排序的ID 1.Twitter的SnowFlake生成ID能够按照时间有序生成 2.SnowFlake算法生成id的结果是一个64bit大小的整数,为一个Long型(转换成...
  • 雪花算法(SnowFlake) 1. 原理 SnowFlake算法生成id的结果是一个64bit大小的整数: 1bit符号位 + 41bit时间戳 + 10bit机器ID + 12bit序列号 由于在Java中64bit的整数是long类型,所以在Java中SnowFlake算法生成的id...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,645
精华内容 1,458
关键字:

自增id雪花id