我正在尝试在 linux 平台上的 java 中的大量多线程环境中异步记录。什么是合适的数据结构(无锁)来引入低线程争用?我需要记录 GB 的消息。我需要以异步/无锁方式执行此操作,因此我不会破坏主要逻辑(调用记录器 API 的代码)的性能。
5 回答
Logback 有一个可能满足您需求的 AsyncAppender。
我会使用Java Chronicle,主要是因为我编写了它,但我建议在这里使用它,因为您可以使用最少的操作系统调用编写无锁和无垃圾日志记录。这需要每个线程一个日志,但我假设您已经将这些保持在最低限度。
我已经使用这个库从两个线程中写入 1 GB/秒。如果日志记录对您来说是一个瓶颈,您可能会发现拥有更多线程并没有您想象的那么大。
顺便说一句:您让我了解了如何从多个线程/进程更新日志,但实施和测试需要一段时间。
最简单的方法是写入多个文件 - 每个线程一个。
确保将时间戳放在每条记录的开头,这样更容易将它们合并到单个日志文件中。
示例 unix 命令:
cat *.log | sort | less
但是为了获得更好/更有用的答案,您确实需要通过添加更多细节来澄清您的问题。
避免队列争用是不可能的,因为您的日志线程很可能会比您的写入器(磁盘 i/o)线程可以跟上的速度更快,但是通过一些智能等待策略和线程固定,您可以最大限度地减少延迟并最大限度地提高吞吐量。
看看由 Coral Blocks(我隶属于它)开发的CoralLog ,它使用无锁队列,平均可以在 52 纳秒内记录一条 64 字节的消息。它每秒能够写入超过 500 万条消息。
为了减少争用,您可以首先将日志消息放在每个线程专用的缓冲区中。当缓冲区已满时,将其放入由单独的日志线程处理的队列中,然后合并来自不同线程的消息并将它们写入文件。请注意,在任何情况下都需要单独的线程,以免在将下一个缓冲区写入磁盘时减慢工作线程。