多线程环境下的高效异步日志系统

https://github.com/chenlujiu/High-Performence-AsyncLogStream.git

多线程双缓冲异步日志

简介

仿照了MUDUO的日志设计,在原有的基础上做了简化,仅供学习。

使用环境

  • OS: Ubuntu 14.04
  • Complier: g++ 4.8

整体结构

五个头文件

  • FileUtil
  • LogFile
  • AsyncLogging
  • LogStream
  • Logging

FileUtil是对所操作文件的封装,包含了对文件的操作,打开,关闭,appen写,用buffer设置了一个缓冲区。

LogFile是对FileUtil的进一步封装,主要功能是提供一个每过若干次写入就自动执行一次flush的功能。

AsyncLogging是整个日志系统的核心部分,前后端缓冲的交换规则都在这里进行了定义,日志系统的大部分操作都是在这里执行。

LogStream提供了一块缓冲区用来缓存具体使用数据时所写的一行日志,而且格式化了输入,重载了<<运算符。日志系统没有使用printf和iostream主要是因为效率问题。

Logging是对外接口,它定义了使用日志的方式,内含一个LogStream对象,并且在每次使用日志的时候在内容中加上时间、文件名、行号等内容。

技术要点

异步实现

这个日志模块用于多线程环境,在多线程环境下为每一个需要日志服务的线程创建一个背景线程,由当前线程生成日志,背景线程负责把日志写入日志文件。 分为前端后端的好处是,对于前端来讲,写入日志低延迟,低CPU开销,无阻塞,不会让日志成为服务器的瓶颈,对于后端来讲,日志被打包成块,极大的减少了调用IO的次数,做到了足够大的吞吐量,占用较少的资源。

缓冲

这里先解释一下用缓冲区的目的,其实很显然,为了减少写入磁盘的次数,我们总不能生成一条日志就执行一次写操作,这太浪费时间了,所以我们用一个缓冲区来吧日志先存储起来,然后整块整块的向文件里写。

双缓冲

双缓冲就是异步的实现方法,试想如果只有一个缓冲区,那就没有分前后端的必要了,就简单的向一个缓冲区里写,写满了就往文件里写,向文件里写的过程中,程序也不可能在动用这块缓冲区,这完全就变成了顺序执行。

具体方法如下。前端和后端分别都有一块缓冲区,当前端缓冲区写满之后,交换前后端缓冲区,让后端把数据写入文件,而前端则向交换来的空缓冲里填充新的日志信息,如此往复。这样在前端生成日志的时候不必等待磁盘文件操作。具体在实现的时候还要考虑到日志写入过快而后端没有及时处理的情况,这时候可能要临时newbuffer出来,否则会导致日志丢失,具体可以看代码。

另外,为了及时将日志消息写入文件,即便bufferA未满,日志库也会每三秒执行一次上述交换写入操作。

猜你喜欢

转载自blog.csdn.net/qq_33113661/article/details/88529703