首页 > 编程语言 >使用 MybatisPlusCore 自带的雪花算法生成不重复数字

使用 MybatisPlusCore 自带的雪花算法生成不重复数字

时间:2023-04-02 14:46:58浏览次数:93  
标签:数字 19 boot 雪花 生成 算法 自带 MybatisPlusCore

这里不介绍雪花算法的实现原理,可以自行搜索查阅网上的资料。这里主要介绍雪花算法的使用场景,如何调用第三方类库 Mybatis Plus Core 自带的方法来使用雪花算法。

雪花算法的主要使用场景,就是生成不重复的数字,作为数据库表的主键使用。你可能会使用 uuid 作为主键,但是其占用 16 个字节长度,具有无序性,在表中数据量大的情况下,会引起数据位置频繁变动,不利于索引的维护,对于批量数据的增删改具有严重性能影响,Mysql 官方也不推荐使用 uuid 作为表的主键。

使用数字作为数据库表的主键,是最佳实践。其优点在于占用空间小(最多8个字节),查询性能和索引维护效率高,目前雪花算法是业界公认的生成不重复数字非常高效的算法,其算法简单,分布式高并发环境下,能够实现每秒生成百万个不重复数字,被国内外互联网厂商普遍使用。

雪花算法唯一的缺点就是依赖于服务器的时钟,如果时钟回拨,可能会生成重复的数字。该缺点也是可以配合其它方案进行解决的。


代码实现

新建一个 SpringBoot 项目,在 pom 文件中只需要引用 mybatis-plus-core 的 jar 包即可,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.9</version>
    </parent>
    <groupId>com.jobs</groupId>
    <artifactId>XueHuaNumber</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>XueHuaNumber</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!--只需要引用 Mybatis plus core 的组件即可使用其内置的雪花算法-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>3.5.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

项目的结构如下图所示,代码的执行在测试类 XueHuaNumberApplicationTests 中

image

具体代码细节如下:

package com.jobs.xuehua;

import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.*;

@SpringBootTest
class XueHuaNumberApplicationTests {

    //使用雪花算法生成单个 19 位数字,每次生成的数字都不同
    @Test
    void SingleXueHuaNumber() {
        //Mybatis plus core 内置的类,自带雪花算法函数。
        DefaultIdentifierGenerator dig = new DefaultIdentifierGenerator();
        long result = dig.nextId(new Object());
        System.out.println(result);
    }

    //使用雪花算法批量生成若干个 19 位数字,从生成结果来看,是连续的数字
    @Test
    void BatchXueHuaNumber() {
        //Mybatis plus core 内置的类,自带雪花算法函数。
        DefaultIdentifierGenerator dig = new DefaultIdentifierGenerator();

        long result;
        for (int i = 0; i < 100000; i++) {
            //使用雪花算法生成一个 19 位的数字
            result = dig.nextId(new Object());

            //为了节省控制台空间,只打印前 1000 个数字
            if (i <= 1000) {
                System.out.println(result);
            }
        }
    }

    //使用雪花算法,生成 19 位数字,转换为字符串,打散字符串的顺序,从而生成不连续的数字
    @Test
    void BatchRandomNumber() {
        //使用 map 存储生成的数字,最后用于判断在一次批量生成的过程中,是否存在重复的数字
        HashMap<String, String> hm = new HashMap<>();
        //Mybatis plus core 内置的类,自带雪花算法函数。
        DefaultIdentifierGenerator dig = new DefaultIdentifierGenerator();

        //程序执行开始时间戳
        long start = System.currentTimeMillis();

        String temp, result;
        List<String> slist;
        for (int i = 0; i < 100000; i++) {
            //雪花算法获取一个 19 位数字字符串
            temp = dig.nextId(new Object()).toString();
            //将字符串转换为 list
            slist = Arrays.asList(temp.split(""));
            //利用 Collections 自带的方法,打乱 list 中字符串的顺序
            Collections.shuffle(slist);
            //合并打乱后的字符串
            result = String.join("", slist);
            //添加到 hashmap 中,看看是否有重复
            hm.put(result, "");
            //将打乱后的字符串,并打印出来(为了节省控制台空间,只打印前 1000 个数字)
            if (i <= 1000) {
                System.out.println(result);
            }
        }

        long end = System.currentTimeMillis();
        long dural = end - start;
        System.out.println("随机 100000 个数字,耗费时间:" + dural + " 毫秒");
        System.out.println("hashmap 中的数据数量为:" + hm.size());
    }

    //Mybatis plus core 内置的类,也封装了有生成 uuid 的函数,其生成的 uuid 去掉了横线
    @Test
    void getUuidCompare() {
        String uidjdk = UUID.randomUUID().toString();
        System.out.println("Jdk 自带方法生成的 uuid 为:" + uidjdk);

        System.out.println("-----------------------------------");

        DefaultIdentifierGenerator dig = new DefaultIdentifierGenerator();
        String uid = dig.nextUUID(new Object());
        //从打印的结果来看,已经去掉了 uuid 种的横杠
        System.out.println("mybatis core 自带方法生成的 uuid 为:" + uid);
    }
}

这里说一下 BatchRandomNumber 这个方法。为了确保生成的数字具有不连续、不重复的特点,实现步骤如下:

  1. 采用雪花算法生成一批数字

  2. 将每个数字转换为字符串,将字符串转换为字符列表

  3. 使用 Jdk 自带的 Collections.shuffle 方法,将字符列表随机打乱

  4. 将打乱后的字符列表,再拼接组成最终的数字字符串

理论上来讲,经过这一波操作,生成的字符串重复概率极低,从全局角度上来看,基本上可以认为不重复。

因为对于同一个 19 位的字符串来说,根据高中的数学排列公式,可以计算出其随机排列后的结果可能性数量如下:

image

A(19 , 19)= 19 的阶乘 / 0 的阶乘 = 121,645,100,408,832,000

备注:0 的阶乘等于 1

由此可见,对于同一个 19 位字符串,随机排列后就有 十亿个亿 种结果,重复概率可以忽略不计,更何况雪花算法生成的每个数字都不一样,每个都需要进行打散随机再排列,所以从理论上来看,数字重复的概率极低,可以基本上认为不重复。


本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/XueHuaNumber.zip

标签:数字,19,boot,雪花,生成,算法,自带,MybatisPlusCore
From: https://www.cnblogs.com/studyjobs/p/17280442.html

相关文章

  • 【Linux Centos】如何卸载自带的python和yum以及卸载后如何重新安装yum
    【LinuxCentos】如何卸载自带的python和yum以及卸载后如何重新安装yum注意如果不是必要情况,请不要卸载服务器自带的python,因为yum等命令都会用到python库,卸载以后可能造成不良后果。如果只是觉得系统python版本不合适,想安装新版本,建议安装anaconda或miniconda,在不同的环境中使......
  • 【算法学习】图论模板
    注意!并查集只适用于无向图。DFS特点:当前层可以获得下层状态、向下层不断遍历处理方式:递归模板://dfs注意剪枝voiddfs(intu){if(u>n){输出路径return;}for(inti=0;i<n;i++)//遍历点{if(条件)......
  • Layui open()弹窗中的表单实现Layui自带的验证功能
    在 layer.open中的 success回调方法里增加如下代码:layero.addClass('layui-form');layero.find(".layui-layer-btn0").attr({"lay-filter":"addSubmit","lay-submit":""});  ......
  • 算法随想Day51【单调栈】| LC739-每日温度、LC496-下一个更大元素Ⅰ
    LC739.每日温度vector<int>dailyTemperatures(vector<int>&temperatures){intsize=temperatures.size();vector<int>result(size,0);vector<int>sta;sta.push_back(0);for(inti=1;i<size;++i){......
  • 算法随想Day52【单调栈】| LC503-下一个更大元素Ⅱ、LC42-接雨水
    LC503.下一个更大元素Ⅱ对于“每日温度”,相当于对nums数组,进行了两次遍历。用i%size所得余数作为下标,且循环的圈数为size*2vector<int>nextGreaterElements(vector<int>&nums){intsize=nums.size();vector<int>result(size,-1);vector<int>sta;......
  • 算法随想Day53【单调栈】| LC84-柱状图中最大的矩形
    intlargestRectangleArea(vector&heights){intresult=0;stackst;heights.insert(heights.begin(),0);heights.push_back(0);st.push(0);for(inti=1;i<heights.size();i++){if(heights[i]>heights[st.top()]){st.push(......
  • Quine-McCluskey算法简介及其C++代码实现
    AlgorithmListallminterms(anddon'tcareterms)Stepbystepmergingonelayeratatime(notethatonlytwominimumtermswithadistanceof1canbemerged),andpayattentiontoremovingduplicatesFindtheessentialprimeimplicationthrough......
  • 机器——算法
    上位机(计算机视觉)(AGX)下位机(单片机)控制具体硬件(STM32)GPIOSTM32基于ARM的32位微控制器F通用类型407产品子系列Z引脚数目:T36C48R64V100Z144G闪存存储器容量实验内容控制LED灯闪烁需要具备的能力单片机编程能力C/C++设计能力查阅资料能力......
  • golang蒙特卡洛树算法实现五子棋AI
    已经实现蒙特卡洛树算法的通用逻辑,只需要对应结构体实现相关接口就可以直接使用该算法。优化算法主要优化GetActions生成下一步动作,要尽可能少,去掉无意义的动作。以及优化ActionPolicy从众多动作挑选比较优秀的动作。对应五子棋就是执行该动作后当前局面评分最高。packagemain......
  • 进程调度算法
    1、先来先服务FCFS非抢占式,按照请求顺序来进行调度。有利于长作业,不利于短作业,短作业等待时间长。2、最短作业优先非抢占式,按照运行时间最短顺序调度。长作业可能饿死,等待短作业一直得不到运行。3、最短剩余时间优先短作业的抢占式版本,按剩余时间调度。4、时间片轮转按FC......