mybatis-plus 雪花算法id冲突问题解决、雪花算法id冲突、雪花算法、id冲突解决、id、id冲突、主键冲突

2024-09-05 10:36

本文主要是介绍mybatis-plus 雪花算法id冲突问题解决、雪花算法id冲突、雪花算法、id冲突解决、id、id冲突、主键冲突,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

mybatis-plus 雪花算法id冲突问题解决、雪花算法id冲突、雪花算法、id冲突解决、id、id冲突、主键冲突

问题:
k8s里起了多个pod,发现mybatis-plus的雪花算法不同pod之前生成了相同的id

问题原因:
mybatis-plus默认id生成器生成datacenterId时是读取的机器网卡mac地址后两个字节,生成一个0~31的数字,这里有很大机率生成相同的datacenterId值
mybatis-plus默认id生成器生成workerId时是读取的jvm pid,但是k8s里pod的jvm pid不作处理时默认都是1,导致datacenterId + workerId有很大机率不同的pod拥有相同的值

分析日志:
ee:dc:39:3f:1a:53
531a >> 6 = 0101001100
0101001100 % 32 = 01100

86:65:49:0a:d1:f4
f4d1 >> 6 = 1111010011
1111010011 % 32 = 10011

e2:71:3a:cc:31:c3
c331 >> 6 = 1100001100
1100001100 % 32 = 01100

解决思路:
不同的pod之间分配唯一的datacenterId、workerId,使生成的雪花算法id不会产生冲突

解决方案(已实际使用并已通过测试):

//程序配置
application.yml:mybatis-plus-ext:snowflake:redis-key: smarthome.mybatis-plus-ext.snowflake.redis-key #mybatis-plus 雪花算法生成器配置。解决多个pod情况下生成的 数据中心id+workerId 重复的问题的redis键值


 

//配置类
MybatisPlusSnowflakeConfig.java:package com.onbright.smarthome.config;import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;/*** <p>* mybatis-plus 雪花算法生成器配置。解决多个pod情况下生成的 数据中心id+workerId 重复的问题* </p>*/
@Slf4j
@Configuration
public class MybatisPlusSnowflakeConfig {@Autowiredprivate RedisTemplate redisTemplate;@Value("${mybatis-plus-ext.snowflake.redis-key}")private String redisKey;@Beanpublic IdentifierGenerator identifierGenerator(){//testedLong redisIncrementValue = redisTemplate.opsForValue().increment(redisKey, 1L);if (redisIncrementValue == null || redisIncrementValue < 0L){throw new RuntimeException(String.format("程序启动失败, 使用redis获取到的雪花算法索引值异常, %s", redisIncrementValue));}//tested//从redis索引值中取出dataCenterId、workerIdMutablePair<Long, Long> longLongMutablePair = generateDatacenterIdAndWorkerIdFromIndex(redisIncrementValue);Long dataCenterId = longLongMutablePair.getLeft();Long workerId = longLongMutablePair.getRight();//tested//再次检查dataCenterId、workerId值if (dataCenterId == null || dataCenterId < 0L || dataCenterId > 31L|| workerId == null || workerId < 0L || workerId > 31L){throw new RuntimeException(String.format("程序启动失败, 使用雪花算法索引值算出的dataCenterId,workerId异常, %s, %s, %s", redisIncrementValue, dataCenterId, workerId));}log.info("mybatis-plus雪花算法datacenterId,workerId生成, redisIncrementValue: {}, dataCenterId: {}, workerId: {}", redisIncrementValue, dataCenterId, workerId);return new DefaultIdentifierGenerator(workerId, dataCenterId);}/*** 从index值中生成雪花算法的datacenterId(5bit)、workerId(5bit)** @param index 索引值,如:1。必须为大于等于0的值* @return 返回生成好的用MutablePair包装的datacenterId(left)、workerId(right),其中datacenterId值范围为0~31,workerId值范围也为0~31,如:{0,0}、{1、1}、{0,1}、{0,31}、{31,31}* @throws IllegalArgumentException 当参数索引值小于0时会抛出异常*/public static MutablePair<Long, Long> generateDatacenterIdAndWorkerIdFromIndex(long index) {if (index < 0) {throw new IllegalArgumentException("索引值不能为负数");}long indexBucket = index % 1024L;long dataCenterId = indexBucket / 32L;long workerId = indexBucket % 32L;return MutablePair.of(dataCenterId, workerId);}}//测试核心函数
MybatisPlusSnowflakeConfigTest.java:package com.onbright.smarthome.config;import org.apache.commons.lang3.tuple.MutablePair;
import org.junit.Assert;
import org.junit.Test;public class MybatisPlusSnowflakeConfigTest {@Testpublic void generateDatacenterIdAndWorkerIdFromIndex() {//legal{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(0L);Assert.assertEquals(0L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(0L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(1L);Assert.assertEquals(0L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(1L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(2L);Assert.assertEquals(0L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(2L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(31L);Assert.assertEquals(0L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(31L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(32L);Assert.assertEquals(1L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(0L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(33L);Assert.assertEquals(1L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(1L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(63L);Assert.assertEquals(1L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(31L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(64L);Assert.assertEquals(2L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(0L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(991L);Assert.assertEquals(30L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(31L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(992L);Assert.assertEquals(31L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(0L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(993L);Assert.assertEquals(31L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(1L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(1023L);Assert.assertEquals(31L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(31L, longLongMutablePair.getRight().longValue());}{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(1024L);Assert.assertEquals(0L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(0L, longLongMutablePair.getRight().longValue());}//integer.max{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(2147483647L);Assert.assertEquals(31L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(31L, longLongMutablePair.getRight().longValue());}//long.max{MutablePair<Long, Long> longLongMutablePair = MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(9223372036854775807L);Assert.assertEquals(31L, longLongMutablePair.getLeft().longValue());Assert.assertEquals(31L, longLongMutablePair.getRight().longValue());}//illegal{Assert.assertEquals("索引值不能为负数", Assert.assertThrows(IllegalArgumentException.class, () -> MybatisPlusSnowflakeConfig.generateDatacenterIdAndWorkerIdFromIndex(-1)).getMessage());}}
}

这篇关于mybatis-plus 雪花算法id冲突问题解决、雪花算法id冲突、雪花算法、id冲突解决、id、id冲突、主键冲突的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1138715

相关文章

SQL Server配置管理器无法打开的四种解决方法

《SQLServer配置管理器无法打开的四种解决方法》本文总结了SQLServer配置管理器无法打开的四种解决方法,文中通过图文示例介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录方法一:桌面图标进入方法二:运行窗口进入检查版本号对照表php方法三:查找文件路径方法四:检查 S

MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)

《MyBatis-Plus中nested()与and()方法详解(最佳实践场景)》在MyBatis-Plus的条件构造器中,nested()和and()都是用于构建复杂查询条件的关键方法,但... 目录MyBATis-Plus 中nested()与and()方法详解一、核心区别对比二、方法详解1.and()

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

Springboot如何正确使用AOP问题

《Springboot如何正确使用AOP问题》:本文主要介绍Springboot如何正确使用AOP问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录​一、AOP概念二、切点表达式​execution表达式案例三、AOP通知四、springboot中使用AOP导出

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题

《解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘问题》:本文主要介绍解决未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4... 目录未解析的依赖项:‘net.sf.json-lib:json-lib:jar:2.4‘打开pom.XM