关于这个主题,有几篇关于 SO 的帖子。每个人都在谈论一种特定的方法,因此只想在一个问题中进行比较。
Using new Date() as unique identifier
Generating a globally unique identifier in Java
我正在尝试实现一项功能,我们可以在其中识别日志文件中的某些事件。这些事件需要与唯一的 id 相关联。
我正在尝试为这种独特的 ID 生成提出一种策略。
ID 必须有 2 个部分:
一些静态信息+一些动态信息
当需要调试事件时,可以在日志中搜索模式。
我有三种方法:
对于这个问题的范围,多个 JVM 不是考虑因素。
我需要在一个 JVM 上以有效的方式生成唯一 ID。此外,我将无法使用依赖于数据库的解决方案。
上述 3 种策略中哪一种最有效?
最佳答案
我和你有同样的需求,区分日志中与其他无关条目交错的相关条目线程。我已经尝试了您建议的所有三种方法。我的经验是在 4D不是Java,但类似。
日期时间
就我而言,我使用的是解析为整秒的日期时间值。这只是一个太大的粒度。我很容易在同一秒内开始发生多个事件的冲突。该死的那些高速电脑!
在您使用捆绑的 java.util.Date 或 Joda-Time 的情况下(强烈推荐用于其他目的),两者都解析为毫秒。一毫秒在现代计算机中是很长的时间,所以我不推荐这样做。
在 Java 8 中,新的 java.time.* package (受 Joda-Time 的启发,由 JSR 310 定义)解析为纳秒。这似乎是一个更好的标识符,但不是。一方面,您计算机的物理计时时钟可能不支持如此精细的分辨率。另一个是计算机越来越快。最后,计算机的时钟可以重置,实际上它经常被重置,因为计算机时钟漂移了很多。现代操作系统通过频繁检查 time server 来重置他们的时钟在本地或通过 Internet。
此外,日志已经有了时间戳,因此使用日期时间作为我们的标识符并没有得到任何额外的好处。事实上,在日志条目中有第二个日期时间实际上可能会引起混淆。
序列号
通过“原子整数”,我假设您的意思是序列号增加到增加的数字。
这对于您的目的来说似乎有点过分。
因此,这种方法增加了风险,而没有增加任何特殊的好处。
用户名
宾果!正是您所需要的。
UUID很容易生成,使用捆绑的 java.util.UUID 类的能力生成版本 3 或 4 UUID,或使用第三方库,或访问命令行的
uuidgen
工具。对于非常大的容量,[版本 1] UUID ( MAC + 日期时间 + 随机数) 将是最好的。对于日志记录,一个 Version 4 UUID(完全随机)是绝对可以接受的。
发生碰撞并不是一个现实的问题。特别是对于为日志生成的有限数量的值。我很惊讶那些无法理解数字的人说他们永远不会用 UUID 替换序列。然而,当我按下时,我认识的每一位程序员和系统管理员都经历过至少一个序列的失败。
无需担心线程安全。无需担心争用(请参阅我在 another answer of mine 上的测试结果)。
UUID 的另一个好处是它通常的 hexadecimal代表,例如:
6536ca53-bcad-4552-977f-16945fee13e2
……很容易辨认。识别后,读者立即知道该字符串是唯一标识符。所以它在你的日志中的存在是自我记录的。
我发现 UUID 是计算的管道胶带。我一直在寻找它们的新用途。
因此,在相关代码的开头,生成一个 UUID,然后将其嵌入到每个相关的日志条目中。
虽然 UUID 的十六进制字符串表示很难读写,但实际上您只需要扫描开头或结尾的几个数字。或者在我们的现代控制台工具中使用带有搜索和过滤功能的复制粘贴。
一些事实
MDC – 映射诊断上下文
我还没有使用过 MDC,但想指出它......
一些日志框架正在添加对这种标记相关日志条目的想法的支持。这种支持称为映射诊断上下文 (MDC)。 MDC 基于每个线程管理上下文信息。
一篇快速介绍性文章是 Log4j MDC (Mapped Diagnostic Context) : What and Why .
最好的伐木立面,SLF4J , 提供此类 an MDC feature .该外观的最佳实现,Logback , 有一个 chapter documenting its MDC feature .
关于java - 在 Java 中生成唯一 ID,以标记日志中的相关条目组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21536572/