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

news2024/11/15 9:12:41

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

问题描述

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

图片

 

问题分析

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

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

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的值。

问题解决

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

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

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

图片

 

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

# 设置随机
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没有生效,我们继续分析下源码。

项目启动的时候,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)}

这样设置以后发现终于生效了,然后部署一下,问题终于解决了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1074688.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JSONUtil.parse将java对象转为json时,需要在java对象中设置get、set方法

想要使用JSONUtil.parse将java对象转为json格式&#xff0c;但是一直为空&#xff0c;代码如下 public class MyTest {public static void main(String[] args) {Test3<String> test3 new Test3<>("2","hhhhhhaaa");System.out.println(JSON…

Excel统计一列数据中某数字出现的频次函数COUNTIF

一、函数COUNTIF 要统计Excel中一列数据中各个元素出现的频次&#xff0c;可以使用Excel的函数COUNTIF。 假设要统计的数据位于A列&#xff0c;从A1到A10&#xff0c;可以在某小格子中使用以下公式来统计每个元素的频次&#xff1a; COUNTIF($A$1:$A$10, A1) 二、示例 下表…

前端笔记:Create React App 初始化项目的几个关键文件解读

1 介绍 Create React App 是一个官方支持的方式&#xff0c;用于创建单页应用的 React 设置用于构建用户界面的 JAVASCRIPT 库主要用于构建 UI 2 项目结构 一个典型的 Create React App 项目结构如下&#xff1a; ├── package.json ├── public # 这…

[ZJCTF 2019]NiZhuanSiWei - 伪协议+文件包含+反序列化

[ZJCTF 2019]NiZhuanSiWei 1 解题流程1.1 分析1.2 解题 题目源码&#xff1a; <?php $text $_GET["text"]; $file $_GET["file"]; $password $_GET["password"]; if(isset($text)&&(file_get_contents($text,r)"welcome t…

中国替代方案探索:替代谷歌企业邮箱的选择

“谷歌企业邮箱在中国有哪些替代方案&#xff1f;在中国市场上表现出色的企业邮箱有腾讯企业邮箱、网易企业邮箱、阿里企业邮箱以及适合外贸的Zoho Mail企业邮箱。” 在中国由于各种原因&#xff0c;包括网络安全、数据隐私保护以及与GFW(防火长城)等&#xff0c;谷歌企业邮箱并…

unity操作_刚体 c#

刚体Rigidbody 首先在场景中创建一个Plane 位置重置一下 再创建一个Cube 充值 y0.5 我们可以看出创建的Cube 和 Plane都自带碰撞器 Plane用的是网格碰撞器 我们可以通过网格世界看到不同的网格碰撞器 发生碰撞&#xff08;条件&#xff09;&#xff1a; 两个物体都有碰撞器 …

Windows环境下下载安装Elasticsearch和Kibana

Windows环境下下载安装Elasticsearch和Kibana 首先说明这里选择的版本都是7.17 &#xff0c;为什么不选择新版本&#xff0c;新版本有很多坑&#xff0c;要去踩&#xff0c;就用7就够了。 Elasticsearch下载 Elasticsearch是一个开源的分布式搜索和分析引擎&#xff0c;最初由…

C++ 初识STL

STL 1. 初识STL2. STL相关知识学习网站3. STL体系结构4. STL六大组件之间的关系5. STL六大组件使用例子6. 初识容器7. 初识分配器7.1 其他分配器7.2 为什么需要其他的分配器 1. 初识STL STL全称为标准模板库&#xff08;Standard Template Library&#xff09;。设计STL的初衷是…

关于VMware Workstation Pro中虚拟机无法连接外网问题解决

解决方案 1.虚拟机设置 打开虚拟机设置&#xff0c;将网络设备器修改为NAT模式。注意如果是克隆的多个虚拟机&#xff0c;需要将高级&#xff08;V&#xff09;里面的mac地址进行重新生成。 2.配置虚拟网络编辑器 进入虚拟网络编辑器后&#xff0c;将子网和子网掩码进行修…

安卓玩机----展讯芯片机型解锁 读写分区工具 操作步骤解析

国内机型大都使用高通和MTK芯片。展讯芯片使用的较少。相对来说高通和mtk机型解锁以及读取分区工具较多。展讯的几乎没有。目前有大佬开发出了一款展讯芯片解锁 与读写分区工具.开源的tools 官方分享说明&#xff1a; 是一款专为 Windows 计算机设计的免费、用户友好的工具&am…

性价比高的项目管理软件推荐:哪个更适合您?

如今&#xff0c;企业管理软件层出不穷&#xff0c;面对诸多企业管理软件&#xff0c;我们要如何去进行选择。产品的功能都大同小异&#xff0c;当面对如此之多的“衍生品”&#xff0c;我认为首先要考虑的就是性价比。当产品的功能要求都能够满足时&#xff0c;性价比无疑是最…

【Linux】Linux 之用户管理

Linux 之用户管理 1.Linux 下的用户2.配置文件3.用户管理3.1 useradd3.1.1 创建用户并指定用户 ID3.1.2 指定用户的主目录3.1.3 指定用户的主组 3.2 adduser3.3 userdel3.4 密码文件3.4.1 字段含义解释3.4.2 给用户添加密码 3.5 其他与用户相关的命令 4.修改用户的信息4.1 user…

2.6 方法

思维导图&#xff1a; 2.6.1 什么是方法 ### 2.6.1 什么是方法 **定义**: - 方法就是一段可以重复调用的代码&#xff0c;使得程序的可读性、可维护性都得以提高。 **示例**: - 假设有一个游戏中需要反复发射炮弹。而发射炮弹的代码有100行。为了避免在程序中多次写下这100…

Java架构师系统架构设计性能评估

目录 1 导论2 架构评估基础系统性能衡量的基本指标2.1 系统性能的指标2.2 数据库指标2.3 并发用户数2.4 网络延迟2.4 系统吞吐量2.5 资源性能指标3 架构评估基础服务端性能测试3.1基准测试3.2 负载测试3.3 压力测试3.4 疲劳强度测试3.5 容量测试1 导论 本章的主要内容是掌握架构…

【Java】微服务——RabbitMQ消息队列(SpringAMQP实现五种消息模型)

目录 1.初识MQ1.1.同步和异步通讯1.1.1.同步通讯1.1.2.异步通讯 1.2.技术对比&#xff1a; 2.快速入门2.1.RabbitMQ消息模型2.4.1.publisher实现2.4.2.consumer实现 2.5.总结 3.SpringAMQP3.1.Basic Queue 简单队列模型3.1.1.消息发送3.1.2.消息接收3.1.3.测试 3.2.WorkQueue3.…

【Linux升级之路】7_进程信号

目录 一、【Linux初阶】信号入门 | 信号基本概念信号产生核心转储二、【Linux初阶】信号入门2 | 信号阻塞、捕捉、保存 一、【Linux初阶】信号入门 | 信号基本概念信号产生核心转储 链接&#xff1a; 【Linux初阶】信号入门 | 信号基本概念信号产生核心转储 二、【Linux初阶】…

奖品定制经营商城小程序的作用是什么

奖品是激励人员团体很好的方式&#xff0c;也是荣誉象征&#xff0c;奖牌、奖杯、高端礼盒等&#xff0c;同时市场中团体非常多&#xff0c;其需求也是很多&#xff0c;尤其定制方面&#xff0c;就更是不用说。 对奖品定制企业来说&#xff0c;除了线下门店获客经营外&#xf…

使用BAPI_NETWORK_COMP_*实现生产订单组件的增删改查

1、文档说明 对于生产订单组件的增删改有多种办法&#xff0c;比较常用的有使用内部函数CO_XT_COMPONENT_*&#xff0c;有改造BAPI_ALM_ORDER_MAINTAIN来实现&#xff0c;各有千秋。 本文档介绍&#xff0c;通过PS的BAPI_NETWORK_COMP_*系列BAPI&#xff0c;来实现常见的组件…

单链表习题(对应章节chapter2)

题目1&#xff1a;链表的中间结点 题目来源&#xff1a;leetcode链表的中间结点 第一种思路分析&#xff1a;考虑指针移动到相应的位置来做 参考代码&#xff1a;位置&#xff08;/chapter2/c/middle-link-list-node/lc1.cc&#xff09; #include <stdio.h> extern &qu…

Linux 查看是否安装memcached

telnet 127.0.0.1 11211这样的命令连接上memcache&#xff0c;然后直接输入stats就可以得到memcache服务器的版本 安装memcached &#xff1a; sudo apt-get install memcached