分布式 雪花算法 唯一性ID

本文讨论了雪花算法在分布式集群中可能出现的重复ID问题,主要原因是进程号的碰撞。作者提出使用Redis进行标识位的分布式管理,确保每个节点生成的独特ID。核心代码展示了如何利用Redis的原子自增功能来避免ID冲突。
摘要由CSDN通过智能技术生成

背景:雪花算法在分布式集群情况下,会生成重复的数值

雪花算法介绍:

雪花算法由 64bit 组成,刚好凑上 long 的 8 个字节 然后中间有 10bit 是标识符作用,叫 dataCenterId 和 workerId,分别占 5bit

mybatisplus 取 mac 地址作为 dataCenterId,取出 5bit,通过 mac 地址来减少碰撞,然后又将 dataCenterId 和进程号拼接,取hashCode 低 16位,再次减少碰撞

问题出就出在进程号上面, K8s 的进程号都是 1。所以说,如果从 mac 地址上取出的 5位 bit 冲突了,那么相同的多个进程在同一毫秒同一序列号获取的雪花算法就是错的

解决方案:(节点最好低于32个)

雪花算法的标识位使用Redis 统一分配

核心代码:

@Resource
private RedissonClient redissonClient;
private static String key = "sysNo";

//使用redis原子自增,实现分布节点不同机器码
RAtomicLong counter = redissonClient.getAtomicLong(key);
long workId =counter % 32;
if(workId % 32 == 0){
    workId = 1;
}
String macAddr =  getMacAddr();
long dataCenterId = macAddr.hashCode();
if(dataCenterId % 32 == 0){
    dataCenterId = 1;
}
Snowflake snowflake = new Snowflake(workId , dataCenterId);
//生成唯一ID
long uniKey= snowflake.nextId();

//获取节点mac地址

public String getMacAddr (){
    try {
        // 获取所有网络接口
        Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
        while (interfaces.hasMoreElements()) {
            NetworkInterface networkInterface = interfaces.nextElement();
            if (networkInterface.isLoopback() || networkInterface.isVirtual() || !networkInterface.isUp()) {
                continue; // 跳过回环接口、虚拟接口和非活动接口
            }
            byte[] mac = networkInterface.getHardwareAddress();
            if (mac != null) {
                Formatter formatter = new Formatter();
                for (byte b : mac) {
                    formatter.format("%02X:", b);
                }
                String macAddress = formatter.toString().substring(0, formatter.toString().length() - 1); // 移除最后一个冒号
                formatter.close();
                return macAddress;
            } else {
                System.out.println("MAC Address not found for: " + networkInterface.getName());
                return null;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
 

  • 12
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值