对于跟踪非常有用。当这些id包含高分辨率时间戳时,它们会更有用。唯一标识符不仅记录事件发生的时间,而且是唯一的,可以帮助通过系统跟踪事件。根据实现方法的不同,这个唯一时间戳的成本会比较高。接下来,我们在研发中探索了一种轻量级方法来生成独特的、单调递增的纳秒级分辨率时间戳。唯一标识符的用途唯一标识符可用于与一条信息相关联,以便以后可以明确引用该信息。它可以是事件、请求、订单ID或客户ID。他们的业务可以用作数据库或键/值存储中的主键,以便稍后识别该信息。生成这些标识符的挑战之一是在不增加成本的情况下避免创建重复项。我们可以记录在数据库中创建的每个标识符,但是当我们添加更多标识符时,这会使用O(n)存储。您可以生成一个随机标识符,例如不太可能重复的UUID,但是,这会创建相对较大的id(不要只看一个字符串,当等效项很大时,它非常大),否则包含无信息。例如,一个UUID可能看起来像d85686f5-7a53-4682-9177-0b64037af336这个UUID可以存储为16个字节,但通常存储为一个占用40个字节内存的对象。使用256位可降低重复标识符的风险,但会使内存增加一倍。时间戳作为唯一标识符使用时间戳有两个好处。您不需要存储太多信息,因为时钟是驱动程序的。你只有两个线程检查不同的时间,缺点是它在重启时丢失,例如时钟时间应该已经足够长,仍然不会得到重复的时间戳。此类标识符也更易于阅读,并提供对跟踪有用的附加信息。基于时间戳的唯一标识符可能类似于2021-12-20T23:30:51.8453925此时间戳可以存储在LocalDateTime对象中,该对象的长度可以为8个字节。MappedUniqueTimeProvider代码这是GitHub上提供的MappedUniqueTimeProvider的精简版/***时间戳在单个机器上的线程/进程之间是唯一的。*/publicenumMappedUniqueTimeProviderimplementsTimeProvider{INSTANCE;私人最终字节字节;私有TimeProvider提供者=SystemTimeProvider.INSTANCE;MappedUniqueTimeProvider(){Stringuser=System.getProperty("user.name","unknown");MappedFile文件=MappedFile.mappedFile(OS.TMP+"/.time-stamp."+user+".dat",OS.pageSize(),0);bytes=file.acquireBytesForWrite(mumtp,0);}@OverridepubliclongcurrentTimeNanos()throwsIllegalStateException{longtime=provider.currentTimeNanos(),time5=time>>>5;longtime0=bytes.readVolatileLong(LAST_TIME),timeNanos5=time0>>>5;如果(time5>timeNanos5&&bytes.compareAndSwapLong(LAST_TIME,time0,time))返回时间;while(true){time0=bytes.readVolatileLong(LAST_TIME);longnext=(time0+0x20)&~0x1f;如果(bytes.compareAndSwapLong(LAST_TIME,time0,next))返回下一个;Jvm.nanoPause();以下技术已用于确保时间戳的唯一性和效率内存共享TimeProvider使用共享内存来确保纳秒分辨率时间是唯一的内存映射文件以线程安全的方式访问,以确保单调递增的时间戳。ChronicleBytes有一个库支持对内存映射文件的线程安全访问。从内存映射文件中读取一个值并尝试在循环中更新它。CAS或比较和交换操作是原子的,并检查先前的值是否未被另一个线程更改。当然,这是在同一个服务上的一个线程上操作。存储纳秒时间戳我们使用rawlong来存储时间戳以提高效率,但这可能更难使用,我们支持打印和解析称为NanoTimestampLongConverter的长时间戳,我们还解析这些时间戳并隐式渲染为文本使其更容易打印,调试并创建单元测试。publicclassEventextendsSelfDescribingMarshallable{@LongConversion(NanoTimestampLongConverter.class)长时间;}Evente=newEvent();e.time=CLOCK.currentTimeNanos();Stringstr=e.toString();Evente2=Marshallable.fromString(str);System.out.println(e2);Prints!net.openhft.chronicle.wire.Event{time:2021-12-20T23:30:51.8453925}由于纳秒时间戳是一种高分辨率格式,它只会作为有符号长整型持续到2262或2554,在值溢出之前,它可以被假定为无符号长整型。我们已经将时间戳中的额外位置用于其他目的,例如存储主机标识符或源ID。出于这个原因,我们还确保时间戳对于32ns的倍数是唯一的,如果我们愿意,我们可以将低5位用于其他目的。效果在正常操作下,不到50ns就可以在服务器上获得唯一的纳秒时间戳。在繁重的多线程负载下,可能需要数百纳秒。MappedUniqueTimeProvider应用程序可以支持超过3000万/第二代。Restartability这种策略允许所有状态丢失,只要时间不倒退,但仍然只在从时钟上保证唯一性。如果时钟时间确实倒退一个小时,那么状态将确保没有重复,但是,时间戳将不会与时钟匹配,直到时钟赶上。结论可以有一个轻量级的唯一标识符生成器来保存纳秒时间戳。
