您的位置:首页技术文章
文章详情页

mybatis-plus雪花算法自动生成机器id原理及源码

【字号: 日期:2023-10-19 10:44:29浏览:5作者:猪猪
目录1、雪花算法原理2、自动生成唯一机器号源码1、雪花算法原理

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

mybatis-plus雪花算法自动生成机器id原理及源码

1bit,不用,因为二进制中最高位是符号位,1表示负数,0表示正数。生成的id一般都是用整数,所以最高位固定为0。 41bit-时间戳,用来记录时间戳,毫秒级。 10bit-工作机器id,用来记录工作机器id。 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.87InetAddress ip = InetAddress.getLocalHost();NetworkInterface network = NetworkInterface.getByInetAddress(ip);//一般不是null会进入elseif (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原理的详细内容,更多关于mybatis plus雪花id的资料请关注好吧啦网其它相关文章!

标签: Mybatis 数据库
相关文章: