日志系统设计需要考虑的问题:
1.需要保证日志系统收集到的数据的有效性和完整性,在app崩溃时日志不丢失。
2.保证收集日志的过程不影响app的性能,不能占用过高cpu资源,或者频繁IO造成卡顿现象。
简单来说,日志收集就是把app运行过程中产生的一些关键数据,给他采集保存起来,然后上传到后台服务器的过程。
这个采集过程,如果是每产生一次日志数据,就写一次文件,势必造成系统IO调用的频繁操作,可能会造成app运行卡顿现象。
MMAP就非常适用于解决这个问题。
MMAP是什么?
MMAP是一种内存映射文件的方法,将文件或者一些对象映射到进程的地址空间。实现文件磁盘地址跟进程虚拟地址空间中的一段内存空间一一映射关系。在写入进程的这段映射内存后,进程内存页的脏数据会自动回写到文件磁盘空间,这就以写内存的效果来实现了写文件的目的。
使用MMAP进行写日志,不仅解决了逐条日志写文件造成的频繁IO卡顿问题,而且也保证了日志数据的完整性,因为在app崩溃的时候,MMAP写入的映射内存数据也会被操作系统自动回写到文件磁盘空间,所以MMAP确实是高效日志系统的首选。
微信的XLog,美团的Logan都是用的MMAP。
还有另一个问题,如何对日志内容进行压缩,以达到写日志更加高效?
微信的XLog的方案是每产生一条日志,就进行压缩并写一次MMAP,压缩算法是LZ77压缩(基于字典的压缩算法),压缩率可达83.7%。
美团的Logan采用的是流式Gzip压缩方式,每次以16kb为单位,通过z_stream将日志流式进行Gzip压缩,流式可以避免CPU峰值。当然这种方案有个缺点,就是没有完美的解决日志丢失问题,当app发生Crash,有可能丢失尚未写入MMAP的16kb的日志。