java - 像 Log4j 这样的日志框架如何保证日志语句的顺序?
问题描述
这个问题一直困扰着我一段时间,像 Log4j 这样的流行日志框架如何允许并发、异步日志顺序保证日志顺序而没有性能瓶颈,即如果在日志语句L1
之前调用日志语句L2
,L1
那么如何保证在日志文件中之前L2
。
我知道 Log4j2 使用环形缓冲区和序列号,但它如何解决问题仍然不直观。
谁能给出一个直观的解释或指向我做同样的资源?
解决方案
这一切都取决于您所说的“记录顺序”。在谈论单个线程时,会保留日志记录顺序,因为每个日志记录调用都会导致写入。
当异步记录每个日志事件时,它会按照接收顺序添加到队列中,并按照先进/先出顺序进行处理,无论它是如何到达那里的。这并不是很有挑战性,因为编写器是单线程的。
但是,如果您正在谈论跨线程的日志记录顺序,则永远无法保证 - 即使是同步记录 - 因为它不可能。线程 1 可以在线程 2 之前开始记录,但线程 2 可以在线程 1 之前的写入中到达同步点。同样,将事件添加到队列时也会发生同样的情况。在日志记录方法中锁定日志记录调用将保持顺序,但几乎没有任何好处,并且会带来灾难性的性能后果。
在多线程环境中,您完全有可能看到时间戳乱序的日志事件,因为线程 1 解析了时间戳,被线程 2 中断,然后线程 2 解析了时间戳并记录了事件。但是,如果您将日志写入 ElasticSearch 之类的东西,您将永远不会注意到,因为它按时间图对它们进行排序。
推荐阅读
- powershell - PowerShell 拉取所有没有成员的空 DL
- android - 测试我使用 Ruby 和 Appium 的断言是否正确
- r - 当 R 中的结果为负时显示 2 位数字和错误消息
- python - tf.Variable assign 方法打破了 tf.GradientTape
- webrtc - Ice stun 请求包中的提名标志在哪里?
- android - 验证器未将数据保存到 Firebase 数据库
- git - Git:获取所有未推送的分支
- salesforce - 如何将角色字段从“帐户联系人关系”集成到联系人对象字段集
- ruby - 为什么 ngrok 向我发送 403 Forbidden
- python - 如何使用python对齐linux输出