创建基于时间的 UUID

概述

在本文中,我们将会 对 UUIDs 和基于时间的 UUIDs(time-based UUIDs) 进行一些探讨。

当我们在对基于时间的 UUIDs 进行选择的时候,总会遇到一些好的方面和不好的方面,如何进行选择,也是我们将要简要探讨的内容。

同时我们还会对可能会使用类库进行一些比较和探索,以便于我们更好的做出选择。

UUIDs 和 基于时间的 UUIDs

UUID 的全称是 Universally Unique Identifier,中文为通用唯一识别码。

当生成 UUID 的时候,系统总会自动生成一个 128 位的 UUID。基于 UUID 的生产算法的不同,我们会有不同的版本。

UUID 的主要目的就是用来在全世界中唯一标识一个数据,而且需要保证生成的 UUID 在全世界范围内是不重复的。因此我们可以用来标识一个上下文,包括数据库系统,计算机系统中的消息,分布式系统中的对象等等。

为了实现这个目标,我们需要确保哪怕是在同一个时间瞬间生成的 UUID 也是不相同,这样能够让我们更好的利用 UUID 在分布式计算机系统中标识存在的对象。

基于时间的 UUID,通过字面就可以了解到,这个 UUID 是基于时间的,实际上这个 UUID 存在 UUID 设计中的第一版。

这个版本是基于随机数的,使用的基数为每 100 纳秒为一个单位,时间的起点为1582年10月15日。同时还需要加上当前计算机的网卡物理地址(MAC)。

在后续的版本中,UUID (v6 和 v7)也是基于时间的 UUID 生成算法,可以说是基于 UUID v1 的更新版本。

UUID v1 因为是基于时间的,所以具有排序功能,这个在对数据库的设计上就很有帮助,当我们使用 UUID v1 来作为 PK(主键)的时候,我们就知道了,我们创建的这条记录的时间戳是什么时候,这个对我们在对数据进行调试和问题分析的时候就很有帮助了。

有优势就自然会有劣势,因为我们是基于时间创建 UUID 的,那么在同一个系统产生 UUID 冲突的可能性就会大很多,假设在同一个时间点,我们创建了很多个 UUID,那么大概率就会有出现冲突,重复出现的情况。

在本文的后部分,我们会对这个可能出现的情况进行一些探索。

另外一个原因,就是在 UUID v1 版本中使用主机地址这种做法会潜在的增加系统的安全性问题。这就是 UUID v6 尝试希望解决的问题。

对比程序

为了对可能出现的 UUID 冲突进行演示。我们尝试使用程序来对比可能出现 UUID 冲突的可能性。

这个程序,将会创建 128 个线程,在每个线程中将会生成 100,000 个 UUID。

首先我们对需要使用的变量来进行一些初始化:

    int threadCount = 128;
    int iterationCount = 100_000;
    Map<UUID, Long> uuidMap = new ConcurrentHashMap<>();
    AtomicLong collisionCount = new AtomicLong();
    long startNanos = System.nanoTime();
    CountDownLatch endLatch = new CountDownLatch(threadCount);

如上面的程序所表示的内容,我们定义了 128 个线程,在这 128 个线程中,我们会循环 100,000 次。

同时,我们还初始化了一个 ConcurentHashMap 把我们生成的 UUID 存储到 ConcurentHashMap 中。

同时,我们还会记录出现 UUID 冲突的次数。

为了记录程序的性能,我们对程序开始时间和程序的结束也都进行了存储。在最后我们定义了一个 latch 等待所有线程的执行完成。

当定义完成后变量后,我们就需要启动线程并对线程序进行执行。

    for (long i = 0; i < threadCount; i++) {
        long threadId = i;
        new Thread(() -> {
            for (long j = 0; j < iterationCount; j++) {
                UUID uuid = Generators.timeBasedGenerator().generate();
                Long existingUUID = uuidMap.put(uuid, (threadId * iterationCount) + j);
                if(existingUUID != null) {
                    collisionCount.incrementAndGet();
                }
            }
            endLatch.countDown();
        }).start();
    }

在 UUID 的创建过程中,我们使用了 fasterxml 包中的 Generators,这个 Generators 使用的是 java.util.UUID 类来创建的。

在创建 UUID v1 的使用,使用 fasterxml 是我们常用的做法。

当 UUID 创建后,我们就把创建好的 UUID 存储到 Map 中,UUID 为 map 的 Key,当我们的 UUID 重复出现冲突的时候,Map 将会提示错误,我们程序就会捕获这个错误,然后把出现错误的计数器 + 1。

endLatch.await();
System.out.println(threadCount * iterationCount + " UUIDs generated, " + collisionCount + " collisions in "
        + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos) + "ms");

在程序的最后,CountDownLatch 的 await() 方法会等待所有的线程完成。

当所有线程完成后,我们就会把结果打印在计算机屏幕上。

下面就让我们开始对程序进行运行。

12800000 UUIDs generated, 0 collisions in 16913ms

上面出现了程序的运行结果,我们可以看到并没有出现 UUID 冲突的问题。

uuid-creator

Java UUID Creator 小巧并且使用比较广泛的 UUID 生成器。

使用这个生成器能够为你生成各种 UUID,但从使用的情况上来看并不如 java-uuid-generator 使用得更加频繁。

依赖

如希望在项目中使用这个生成器,需要把这个生成器添加到依赖中。

com.github.f4b6a3 uuid-creator 5.3.7 Copy

使用

这个库提供了 3 个基于时间生成的 UUID 方法。

  • UuidCreator.getTimeBased() – 遵守 RFC-4122 规范生成基于时间的 UUID
  • UuidCreator.getTimeOrdered() – 使用 gregorian epoch 处理的新 UUID 格式
  • UuidCreator.getTimeOrderedEpoch() – 使用 Unix epoch proposed 处理的新 UUID 格式

当我们导入包后,可以直接使用下面的方法来进行使用。

System.out.println("UUID Version 1: " + UuidCreator.getTimeBased());
System.out.println("UUID Version 6: " + UuidCreator.getTimeOrdered());
System.out.println("UUID Version 7: " + UuidCreator.getTimeOrderedEpoch());

我们可以看到生成 UUID 为我们通常认识的 UUID 格式。

UUID Version 1: 0da151ed-c82d-11ed-a2f6-6748247d7506
UUID Version 6: 1edc82d0-da0e-654b-9a98-79d770c05a84
UUID Version 7: 01870603-f211-7b9a-a7ea-4a98f5320ff8

冲突校验

我们还可以使用上面提供的生成代码放我我们开始的一部分使用的冲突校验程序中运行。

运行的结果为:

12800000 UUIDs generated, 0 collisions in 2595ms

通过这个库生成的基于时间的 UUID 我们也没有发现有冲突的情况。

Java UUID Generator (JUG)

依赖

Java UUID Generator (JUG) 在很多项目中因为要生成 UUID 而被使用,其中包括了有 生成UUID 的方法和格式化输出等一些内容。

生成的 UUID 是按照 (RFC-4122) 标准来生成的。

使用下面的代码来添加依赖,当前使用的最新版为 5.0.0

<dependency>
    <groupId>com.fasterxml.uuid</groupId>
    <artifactId>java-uuid-generator</artifactId>
    <version>5.0.0</version>
</dependency>

使用

这个库也同时提供了 3 个方法来生成基于时间的 UUID(包括 v1,v6 和 v7)。

我们可以使用下面的方法来进行命令的调用:

System.out.println("UUID Version 1: " + Generators.timeBasedGenerator().generate());
System.out.println("UUID Version 6: " + Generators.timeBasedReorderedGenerator().generate());
System.out.println("UUID Version 7: " + Generators.timeBasedEpochGenerator().generate());

当程序完成运行后,可以从控制台中看到输出:

UUID Version 1: e6e3422c-c82d-11ed-8761-3ff799965458
UUID Version 6: 1edc82de-6e34-622d-8761-dffbc0ff00e8
UUID Version 7: 01870609-81e5-793b-9e4f-011ee370187b

校验

将新的生成程序替换掉我们原有的代码的时候,我们可以对生成进行输出校验。

12800000 UUIDs generated, 0 collisions in 15795ms

从上面的输出来看,针对代码我们并没有发现有 UUID 冲突的问题。

但是针对运行结果,生成 UUID 的时间是不同的,这是因为 JUG 的生成速度通常要慢一点,对于我们 UUID 来说如果不大量一次性生成 UUID,这个通常不会是太大的问题。

在项目中,通常需要选择项目已有的依赖,可能在现有的项目中,使用 java-uuid-generator 库的情况要相对多一点。

结论

在本文中,我们对需要生成基于时间的 UUID 进行了一些探讨。同时基于时间的不同,UUID 有不同的版本。

JDK 自己并没有提供快速的基于时间的 UUID 生成方法。

JDK 中的 UUID.randomUUID() 方法生成的是 UUIDv4 的方法。

基于时间的 UUID 生成,我们通常会依赖使用第三方的类库。

创建基于时间的 UUID - Java - iSharkFly概述在本文中,我们将会 对 UUIDs 和基于时间的 UUIDs(time-based UUIDs) 进行一些探讨。 当我们在对基于时间的 UUIDs 进行选择的时候,总会遇到一些好的方面和不好的方面,如何进行选择,也是我们将要简要探讨的内容。 同时我们还会对可能会使用类库进行一些比较和探索,以便于我们更好的做出选择。 UUIDs 和 基于时间的 UUIDsUUID 的全称是 Universally Unique Identi…icon-default.png?t=N7T8https://www.isharkfly.com/t/uuid/15686

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数字签名学习

1 基本概念 数字签名是一种加密技术&#xff0c;用于验证信息来源的身份和数据的完整性。 就是对一个东西签上自己的名&#xff1b;收到的人可以验证这东西是你发的&#xff1b;这里是用数字的方式&#xff1b; 对字符串也可以签名&#xff0c;签名以后&#xff0c;还是一个…

《面向云计算的零信任体系第1部分:总体架构》行业标准正式发布

中华人民共和国工业和信息化部公告2024年第4号文件正式发布行业标准&#xff1a;YD/T 4598.1-2024《面向云计算的零信任体系 第1部分&#xff1a;总体架构》&#xff08;后简称“总体架构”&#xff09;&#xff0c;并于2024年7月1日正式施行。 该标准由中国信通院牵头&#xf…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.5

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

web安全---CSRF漏洞/OWASP-CSRFTester的使用

what 跨站请求伪造 Cross Site Request Forgery how 攻击者诱骗点击恶意网页&#xff0c;盗用&#xff08;伪造&#xff09;受害者的身份&#xff0c;以受害者的名义向服务器发送恶意请求,而这种恶意请求在服务端看起来是正常请求 CSRF&&XSS区别 他们最本质区别就…

什么是中间件?中间件有哪些?

什么是中间件&#xff1f; 中间件&#xff08;Middleware&#xff09;是指在客户端和服务器之间的一层软件组件&#xff0c;用于处理请求和响应的过程。 中间件是指介于两个不同系统之间的软件组件&#xff0c;它可以在两个系统之间传递、处理、转换数据&#xff0c;以达到协…

ArcGIS基础:便捷分享图层包和地图包

1、分享图层包&#xff1a; 首先&#xff0c;选中要分享的数据&#xff0c;右键创建图层包&#xff0c;修改保存路径。 找到项目描述那一栏&#xff0c;将摘要、标签、描述都填写分享图层包的相关内容。 一切设置好之后&#xff0c;点击右上角的【分析】按钮。 点击分析之后…

linux下安装anaconda

顺手点个关注吧&#xff0c;谢谢&#xff01; 一、下载安装包 https://repo.anaconda.com/archive/ 或者使用命令 wget https://repo.anaconda.com/archive/Anaconda3-5.3.1-Linux-x86_64.sh2.赋予权限并安装 # 给文件执行权限 chmod 777 Anaconda3-5.3.1-Linux-x86_64.sh# 执…

高频面试题:在浏览器搜索框中输入一个URL的完整请求过程?

相信很多小伙伴在校招或者社招面试中都遇到过这个问题 面试官&#xff1a;小伙子&#xff0c;了解 在浏览器搜索框中输入一个URL的完整请求过程吗&#xff1f;详细说说我&#xff1a;eeemm&#xff0c;不太清出具体的过程。整体过程应该是HTTP请求的过程。 如果在面试中不能很…

FinClip :可以让小程序脱离微信环境最快运行在自有App中

&#x1f9d0; 什么是FinClip&#xff1f; FinClip&#xff0c;一个可以让小程序脱离微信环境&#xff0c;最快运行在自有App中的神器。它支持在iPhone、Android、Windows、Linux、macOS、统信等平台下的应用中运行小程序&#xff0c;这意味着&#xff0c;无论是移动端、PC端&…

uniapp自定义返回事件(封装)

uniapp自定义返回事件 在我们使用uniapp时&#xff0c;我们导航栏一般都是自定义的&#xff0c;比如用uview框架的导航栏&#xff0c;那么返回事件通常会遇到以下几个问题 返回事件前需要做一些额外的处理 h5项目刷新页面后返回失效 返回按钮点击后到指定页面 如果只是监听返…

技术团队的管理方法和日常总结建议

管理学家德鲁克有言“管理是一种实践&#xff0c;其本质不在于知&#xff0c;而在于行&#xff0c;其验证不在于逻辑&#xff0c;而在于成果&#xff0c;其唯一的权威就是成就” &#xff0c;因此管理重实践看效果&#xff0c;但如果管理实践有理论依凭&#xff0c;那么实践起来…

新媒体运营-----短视频运营-----PR视频剪辑----视频调色

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1. Lumetri调色&#xff0c;明暗对比度2. Lumetri调色&#xff0c;创意与矢量示波器2.1 创意2.2 矢量示波器 3. L…

滑块验证码破解----Java使用opencv后端破解滑块验证

使用技术:Java SpringBootopenCV 在windows上首先需要下载opencv进行安装,先去官网:Releases - OpenCV 下载这个windows版本的安装包 下载后直接安装解压就行,然后需要,然后找到安装位置里的这个文件: 你下载的是什么版本的,这里的数字就是多少,比如我下载4.5.3版本那么这…

分治策略 --- 快排归并

目录 分治-快排 一、颜色分类 二、排序数组 三、数组中的第K个最大元素 四、库存管理 分治-归并 一、排序数组 二、交易逆序对的总数 三、计算右侧小于当前元素的个数 四、翻转对 分治是一种思想&#xff0c;也就是将大问题分解成小问题&#xff0c;一直分到小问题可…

2024年云仓酒庄新动态合肥北京双城开课,持续培训助力酒业发展

云仓酒庄合肥北京双城开课&#xff0c;持续培训助力酒业发展 随着国内酒类市场的不断繁荣与消费需求的日益增长&#xff0c;云仓酒庄作为行业内的稳扎稳打之一的企业&#xff0c;始终致力于提升服务质量和品牌影响力。近日&#xff0c;云仓酒庄在合肥与北京两地同时开设培训课…

qt学习篇---C++基础学习

本学习笔记学习下面视频总结&#xff0c;感兴趣可以去学习。讲的很详细 【北京迅为】嵌入式学习之QT学习篇_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1tp4y1i7EJ/?spm_id_from333.337.search-card.all.click&vd_source8827cc0da16223b9f2ad8ae7111de9e2 目录 C…

JavaScript数组方法练习

第一个练习 ● 计算所有账户的存款总额 const bankDepositSum accounts //定义一个变量.flatMap(acc > acc.movements) //使用flatmap将所有的存款提取&#xff0c;然后组成一个新的数组.filter(mov > mov > 0) //使用filter方法提取所有的正值.reduce((sum, c…

【前端】VUE项目创建

在所需文件夹中打开cmd命令行窗口&#xff0c;输入vue ui 进入web可视化界面选择创建新项目 根据需求依次完成下列选择&#xff0c;下列是参考配置&#xff0c;完成后点击创建项目即可 最终显示完成

upload-labs后续(14-)

图片马 在图片中加入木马&#xff0c;然后上传让浏览器解析&#xff0c;达到上传木马的目的 制作图片马&#xff1a;可以在notepad或者winhex中打开文件&#xff0c;在文件头中加入图片的文件头&#xff0c;再在文件末尾加入木马即可。 图片文件头如下&#xff1a; 1.Png图片…

B站广告推广开户最低需要多少钱?

在竞争激烈的互联网营销环境中&#xff0c;哔哩哔哩&#xff08;B站&#xff09;作为深受年轻人喜爱的视频分享平台&#xff0c;其广告价值不容小觑。对于希望在B站上进行广告推广的企业或个人而言&#xff0c;了解开户流程及成本&#xff0c;选择专业的服务团队至关重要。介绍…
最新文章