温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

mybatis-plus雪花算法自动生成机器id原理的示例分析

发布时间:2021-06-04 14:54:29 来源:亿速云 阅读:479 作者:小新 栏目:开发技术

这篇文章主要介绍了mybatis-plus雪花算法自动生成机器id原理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

1、雪花算法原理

        雪花算法使用一个 64 bit 的 long 型的数字作为全局唯一 id。这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。

mybatis-plus雪花算法自动生成机器id原理的示例分析

  1. 1bit,不用,因为二进制中最高位是符号位,1表示负数,0表示正数。生成的id一般都是用整数,所以最高位固定为0。

  2. 41bit-时间戳,用来记录时间戳,毫秒级。

  3. 10bit-工作机器id,用来记录工作机器id。

  4. 12bit-序列号,序列号,用来记录同毫秒内产生的不同id。即可以用0、1、2、3、…4094这4095个数字,来表示同一机器同一时间截(毫秒)内产生的4095个ID序号。

SnowFlake可以保证:

所有生成的id按时间趋势递增
整个分布式系统内不会产生重复id(因为有datacenterId和workerId来做区分)

        如上大概了解了雪花算法的原理,而且也知道机器号对于雪花算法的重要性。如果机器号一样,可能会出现id重复的情况。

        mybatis-plus自3.3.0开始,默认使用雪花算法+UUID(不含中划线),但是它并没有强制让开发者配置机器号。这一点很是疑惑,这样可能会让不了解雪花算法的人埋下了一个坑。
        但是这么强大的一个框架难道真的没有做优化吗?带着问题,查看了下mybatis-plus雪花算法源码com.baomidou.mybatisplus.core.toolkit.Sequence。最终发现在没有设置机器号的情况下,会通过当前物理网卡地址和jvm的进程ID自动生成。这真的是一个较好的解决方案。一般在一个集群中,MAC+JVM进程PID一样的几率非常小。

2、自动生成唯一机器号源码

核心代码。有两个构造方法,一个无参构造,一个有参构造。

public Sequence() {
    //通过当前物理网卡地址获取datacenterId
    this.datacenterId = getDatacenterId(maxDatacenterId);
    //物理网卡地址+jvm进程pi获取workerId
    this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}

/**
 * 有参构造器
 *
 * @param workerId     工作机器 ID
 * @param datacenterId 序列号
 */
public Sequence(long workerId, long datacenterId) {
    Assert.isFalse(workerId > maxWorkerId || workerId < 0,
            String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
    Assert.isFalse(datacenterId > maxDatacenterId || datacenterId < 0,
            String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
    this.workerId = workerId;
    this.datacenterId = datacenterId;
}
  • 无参构造 开发者没有设置机器号时

  • 有参构造 开发者自行设置机器号

protected static long getDatacenterId(long maxDatacenterId) {
    long id = 0L;
    try {
        //获取本机(或者服务器ip地址)
        //DESKTOP-123SDAD/192.168.1.87
        InetAddress ip = InetAddress.getLocalHost();
        NetworkInterface network = NetworkInterface.getByInetAddress(ip);
        //一般不是null会进入else
        if (network == null) {
            id = 1L;
        } else {
            //获取物理网卡地址
            byte[] mac = network.getHardwareAddress();
            if (null != mac) {
                id = ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) >> 6;
                id = id % (maxDatacenterId + 1);
            }
        }
    } catch (Exception e) {
        logger.warn(" getDatacenterId: " + e.getMessage());
    }
    return id;
}
/**
 * 获取 maxWorkerId
 */
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
    StringBuilder mpid = new StringBuilder();
    mpid.append(datacenterId);
    //获取jvm进程信息
    String name = ManagementFactory.getRuntimeMXBean().getName();
    if (StringUtils.isNotBlank(name)) {
        /*
         * 获取进程PID
         */
        mpid.append(name.split(StringPool.AT)[0]);
    }
    /*
     * MAC + PID 的 hashcode 获取16个低位
     */
    return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
}

感谢你能够认真阅读完这篇文章,希望小编分享的“mybatis-plus雪花算法自动生成机器id原理的示例分析”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI