关于上一个ULID
和下一个ULID
之间的时间戳判断 , 这里从规范文件没看出细节实现 , 先简单做一个永远为true
的分支判断 , 后面再深入研究然后修改 。使用方式如下:
public static void main(String[] args) {MonotonicULIDSpi spi = ULID.monotonicUlid();System.out.println(spi.next());System.out.println(spi.next());System.out.println(spi.next());System.out.println(spi.next());}// 某次运行输出01GFGASXXQXD5ZJ26PKSCFGNPF01GFGASXXQXD5ZJ26PKSCFGNPG01GFGASXXQXD5ZJ26PKSCFGNPH01GFGASXXQXD5ZJ26PKSCFGNPJ
这里为了更加灵活 , 没有采用全局静态属性缓存上一个ULID
实例 , 而是简单使用继承方式实现 。
ULID性能评估引入JMH
做了一个简单的性能测试 , 代码如下:
@Fork(1)@Threads(10)@State(Scope.Benchmark)@BenchmarkMode(Mode.Throughput)@Warmup(iterations = 1, time = 1)@Measurement(iterations = 5, time = 3)@OutputTimeUnit(TimeUnit.MILLISECONDS)public class BenchmarkRunner {private static ULID.MonotonicULIDSpi SPI;@Setuppublic void setup() {SPI = ULID.monotonicUlid();}@Benchmarkpublic UUID createUUID() {return UUID.randomUUID();}@Benchmarkpublic String createUUIDToString() {return UUID.randomUUID().toString();}@Benchmarkpublic ULID createULID() {return ULID.ulid();}@Benchmarkpublic String createULIDToString() {return ULID.ulid().toString();}@Benchmarkpublic String createULIDToCanonicalString0() {return ULID.ulid().toCanonicalString0();}@Benchmarkpublic ULID createMonotonicULID() {return SPI.next();}@Benchmarkpublic String createMonotonicULIDToString() {return SPI.next().toString();}public static void main(String[] args) throws Exception {new Runner(new OptionsBuilder().build()).run();}}
某次测试报告如下(开发环境Intel 6700K 4C8T 32G
, 使用OpenJDK-19
):
BenchmarkModeCntScoreErrorUnitsBenchmarkRunner.createMonotonicULIDthrpt518529.565 ± 3432.113ops/msBenchmarkRunner.createMonotonicULIDToStringthrpt512308.443 ± 1729.675ops/msBenchmarkRunner.createULIDthrpt5122347.702 ± 3183.734ops/msBenchmarkRunner.createULIDToCanonicalString0thrpt550848.135 ± 3699.334ops/msBenchmarkRunner.createULIDToStringthrpt537346.891 ± 1029.809ops/msBenchmarkRunner.createUUIDthrpt5806.134 ±218.622ops/msBenchmarkRunner.createUUIDToStringthrpt5813.380 ±46.333ops/ms
小结本文就ULID
的规范进行解读 , 通过规范和参考现有类库进行ULID
的Java
实现 。ULID
适用于一些"排序ID"生成或者需要"单调ID"生成的场景 , 可以考虑用于数据库键设计、顺序号设计等等场景 。从实现上看它性能会优于UUID
(特别是单调ULID
, 因为不需要重新获取随机数部分 , 吞吐量会提升一个数量级) 。
Demo
项目仓库:
framework-mesh/ulid4j
:https://github.com/zjcscut/framework-mesh/tree/master/ulid4j
- ulid-spec
- crockford-base32
- ulid-creator
经验总结扩展阅读
- vite vue3 规范化与Git Hooks
- 钩子 【pytest官方文档】解读-插件开发之hooks 函数
- 深渊游戏结局解读
- 如何解读芥川龙之介的秋山图
- 襄怎么读
- 中 ?打造企业自己代码规范IDEA插件
- 脚手架规范有哪些
- HashMap底层原理及jdk1.8源码解读
- 规范正交基和标准正交基一样吗
- JS 模块化-05 ES Module & 4 大规范总结