分布式ID的一种生成写法
在分布式环境中,唯一ID生成应用十分广泛,生成方法也多种多样,Hutool针对一些常用生成策略做了简单封装。
Snowflake
分布式系统中,有一些需要使用全局唯一ID的场景,有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。Twitter的Snowflake 算法就是这种生成器。
使用Hutool工具类里面的生成方式,maven依赖包如下:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.10</version>
</dependency>
使用方法如下:
//参数1为终端ID
//参数2为数据中心ID
Snowflake snowflake = IdUtil.getSnowflake(1, 1); long id = snowflake.nextId();
注意IdUtil.createSnowflake每次调用会创建一个新的Snowflake对象,不同的Snowflake对象创建的ID可能会有重复,因此请自行维护此对象为单例,或者使用IdUtil.getSnowflake使用全局单例对象。
终端ID和数据中心ID参考mybatis_plus唯一ID生成:
package com.cmft.cmooc.screen.common; import cn.hutool.core.util.IdUtil; import jodd.util.StringPool; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import java.lang.management.ManagementFactory; import java.net.InetAddress; import java.net.NetworkInterface; @Slf4j @Component public class IdGenerator { /** * 机器标识位数 */ private final long workerIdBits = 5L; private final long datacenterIdBits = 5L; private final long maxWorkerId = -1L ^ (-1L << workerIdBits); private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); /** * 机器标识 ID 部分 */ private final long workerId; /** * 数据标识 ID 部分 */ private final long datacenterId; public IdGenerator() { this.datacenterId = getDatacenterId(maxDatacenterId); this.workerId = getMaxWorkerId(datacenterId, maxWorkerId); } /** * <p> * 获取 maxWorkerId * </p> */ protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { StringBuilder mpid = new StringBuilder(); mpid.append(datacenterId); String name = ManagementFactory.getRuntimeMXBean().getName(); if (StringUtils.isNotEmpty(name)) { /* * GET jvmPid */ mpid.append(name.split(StringPool.AT)[0]); } /* * MAC + PID 的 hashcode 获取16个低位 */ return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1); } /** * <p> * 数据标识id部分 * </p> */ protected static long getDatacenterId(long maxDatacenterId) { long id = 0L; try { InetAddress ip = InetAddress.getLocalHost(); NetworkInterface network = NetworkInterface.getByInetAddress(ip); if (network == null) { id = 1L; } else { byte[] mac = network.getHardwareAddress(); if (null != mac) { id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6; id = id % (maxDatacenterId + 1); } } } catch (Exception e) { log.warn(" getDatacenterId: " + e.getMessage()); } return id; } /** * 生成下一个唯一ID * * @return long */ public synchronized String nextId() { return String.valueOf(IdUtil.createSnowflake(workerId, datacenterId).nextId()); } }

浙公网安备 33010602011771号