Redian新闻
>
MyBatis-Plus 内置雪花算法主键重复问题

MyBatis-Plus 内置雪花算法主键重复问题

公众号新闻

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入芋道快速开发平台知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号等等功能:

  • Boot 地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 地址:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn

来源:Fight/MyBatisPlus-neizhixue
huasuanfazhujianzhongfuwenti


Mybatis-Plus 使用ID_WORKER生成主键id重复

问题描述

目前项目使用的id是mybatis-plus 内置的主键生成策略 ID_WORKER ,最近测试在做性能压测,部署架构是单服务集群的部署方式,然后就发现了id重复的异常,异常如下

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

问题分析

首先分析的是id生成是不是就是重复了,先关掉其中一台机器,单机跑,这个时候发现压到1000的并发都没有出现过id重复,这个说明单机情况下不存在id重复问题,说明只有集群的情况下才会出现。

再分析一下id生成的几个要素,雪花算法的核心能影响到id生成的几个因素:1.服务器时间2.workId(机器 ID 部分)3.datacenterId(数据标识 ID 部分)。先检查了一下服务器时间,都是一样的,然后再看一下workId的生成,我们先看一下源码。

插播一条,如果你近期准备面试跳槽,建议在ddkk.com在线刷题,涵盖 1万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题,还有市面上最全的技术栈500套,精品系列教程,免费提供。

public Sequence() {
   
     
    this.datacenterId = getDatacenterId(maxDatacenterId);
    this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
}
//获取workerId
protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
   
     
        StringBuilder mpid = new StringBuilder();
        mpid.append(datacenterId);
        //代表正在运行的Java虚拟机的名称。
        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);
    }

这里生成的workerId主要核心影响就是获取运行的虚拟机名称,现在猜测就是有可能是由于两台机的虚拟机名称可能一样,导致拿到的workerId一样。这个没有具体去验证,猜测是这样的。那我们尝试修改一下这个workerId的值。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

问题解决

1、 先设置workerId为随机数,这样保证每个机器部署的时候拿到的都是随机数;

# 设置随机
mybatis-plus.global-config.worker-id: ${random.int}

这里你启动项目的时候回发现一个异常

异常很明显,这里的worer id 必选小于31,那我们就需要修改一下随机数

插播一条,如果你近期准备面试跳槽,建议在ddkk.com在线刷题,涵盖 1万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题,还有市面上最全的技术栈500套,精品系列教程,免费提供。

# 设置随机
mybatis-plus.global-config.worker-id: ${random.int(1,31)}

这个时候我们先看一下我们设置参数有没有生效,为了比较明显看到效果,我们直接设置worker-id为一个固定值20,再断点看一下,我们找到com.baomidou.mybatisplus.core.toolkit.IdWorker这个核心类,获取id的核心方法是com.baomidou.mybatisplus.core.toolkit.IdWorker#getId,那我们就在这里加一个断点看下

public class IdWorker {
   
     

    /**
     * 主机和进程的机器码
     */

    private static Sequence WORKER = new Sequence();
 //获取id
    public static long getId() {
   
     
        return WORKER.nextId();
    }

    public static String getIdStr() {
   
     
        return String.valueOf(WORKER.nextId());
    }

    /**
     * <p>
     * 有参构造器
     * </p>
     *
     * @param workerId     工作机器 ID
     * @param datacenterId 序列号
     */

    public static void initSequence(long workerId, long datacenterId) {
   
     
        WORKER = new Sequence(workerId, datacenterId);
    }

    /**
     * <p>
     * 使用ThreadLocalRandom获取UUID获取更优的效果 去掉"-"
     * </p>
     */

    public static String get32UUID() {
   
     
        ThreadLocalRandom random = ThreadLocalRandom.current();
        return new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY);
    }

}

断点后的结果是:

这个时候看到workerId没有生效,我们继续分析下源码。

插播一条,如果你近期准备面试跳槽,建议在ddkk.com在线刷题,涵盖 1万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题,还有市面上最全的技术栈500套,精品系列教程,免费提供。

项目启动的时候,mybatis-plus 会调用一个com.baomidou.mybatisplus.core.MybatisConfiguration#init方法来初始化配置信息,我们看下代码

public void init(GlobalConfig globalConfig) {
   
     
        // 初始化 Sequence
    //这里需要同时设置workerId和datacenterId
        if (null != globalConfig.getWorkerId()
            && null != globalConfig.getDatacenterId()) {
   
     
            IdWorker.initSequence(globalConfig.getWorkerId(), globalConfig.getDatacenterId());
        }
        // 打印 Banner
        if (globalConfig.isBanner()) {
   
     
            System.out.println(" _ _   |_  _ _|_. ___ _ |    _ ");
            System.out.println("| | |\\/|_)(_| | |_\\  |_)||_|_\\ ");
            System.out.println("     /               |         ");
            System.out.println("                        "+MybatisPlusVersion.getVersion()+" ");
        }
    }

我们发现workerId和datacenterId必须同时设置才会获取我们设置的值。

那我们就修改配置一下

# 设置随机
mybatis-plus.global-config.worker-id: ${random.int(1,31)}
mybatis-plus.global-config.datacenter-id: ${random.int(1,31)}

ties

设置随机

mybatis-plus.global-config.worker-id: ${random.int(1,31)}
mybatis-plus.global-config.datacenter-id: ${random.int(1,31)}

这样设置以后发现终于生效了,然后部署一下,问题终于解决了。这里问题虽然解决了,但是workerId重复其实没有实际验证过,如果有验证过的同学欢迎留言。


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
尊嘟假嘟?!除了无限包邮,PLUS会员这次还升级了超多权益!!黑五预测!哪些品牌值得期待:Apple、Lululemon、Dyson...惠普推出首款 16 英寸 Pavilion Plus 笔记本电脑,配备 i7-13700H + RTX 305029岁变性美女因分手怒砍男友, 被关男监后反复问医生: 我还像女人么?NASA Plus成为最新的流媒体竞争对手350刀Apple Magic Keyboard iPad Pro 11 & iPad Air 4th/5th Gen日本29岁变性美女因分手怒砍男友,被关男监后反复问医生:我还像女人么?美国感恩节起源地之旅:PLYMOUTH 普利茅斯 五月花船 17世纪英国清教徒居住村庄 Plimoth PlantationHundreds of Chinese Arrested For Cyberscams in Laos, MyanmarChase MyBonus (Targeted) 消费奖励汇总:Q4活动别忘了加!工农兵学微积分Sam’s Club 会员优惠:基础版 $20(原价 $50),Plus 版 $60(原价 $110)七张图解锁Mybatis整体脉络,让你轻松拿捏面试官超级乐透Plus头奖飚至$900万,南加售出3张彩票中奖$1万Lululemon4折起!Veja/Grow Gorgeous头发防脱7折!同事写了一条 SQL,把 MyBatis 都干翻了。。腾讯不会干涉Key社创作,高德推出驾车巡航,ChatGPT Plus默认启用由3.5改为4,X上线直播,这就是今天的其他大新闻!"妈妈让我来自首",7岁男孩在派出所写下"bǎozhèng书"分享一种灵活的数据权限思路(AOP、反射、MyBatis拦截器)Razer Huntsman V2 Optical Gaming Keyboard purple switch like new本周必buy |​ CW再出爆品!$59平替 $729 巴黎大牌,TOMMY HILFIGER、Lululemon好折20230802龚俊新浪扫楼链接+总结5127 血壮山河之武汉会战 富金山战役 15第八章 现代社会的诞生 (2)【75k 开卡奖励】Barclays JetBlue Plus 信用卡美国马里兰州司法主席:青少年暴力是“我们所有人的失败”Yesterday 这三国十五的月亮谁最圆呢?plus 哲学QA深度操作系统 deepin V23 Beta2 今日发布,修复问题超 450 个MyBatis 动态 SQL 最全教程,这样写 SQL 太爽了!京东宣布PLUS会员无限免邮;三星S24将是一台夸张的直屏机;乐视推出新手机Exclusive Report: China Luxury Brands Power Ranking 2023H1中年男人的生活,一地鸡毛。老金的故事巧用 MyBatis Plus 实现数据权限控制【仅限今天】Cyber Monday Citi TYP 兑换折扣:Apple GC 等 20% Off (1.25 cpp)分布式系统的主键生成方案对比今天起!京东自营降至59元包邮,PLUS会员全年运费无限免!
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。