服务器编程中,日志系统需要满足几个条件

.高效,日志系统不应占用太多资源

.简洁,为了一个简单的日志功能引入大量第三方代码未必值得

.线程安全,服务器中各个线程都能同时写出日志

.轮替,服务器不出故障是不重启的,半年一年的日志放到一个文件会导致文件过大

.及时保存,程序故障导致异常退出,此时需要通过日志诊断问题,不缓冲的日志系统更易用

著名的日志库有log4xxx系列,提供了非常灵活的功能,当然随之而来的代价就是庞大的库。在大多数服务器应用中,所需的功能不多,我偏向于选择一个支持按时间轮替的简洁的日志库。

为了同时做到线程安全和支持轮替,大多数日志系统都使用锁。写出日志时,首先获取锁,如果需要轮替,则进行轮替操作,否则写到现有文件,最后释放锁。

google开源的leveldb的日志系统中,同时做到了“线程安全”和轮替,但是没有用锁,这引发了我的兴趣。

仔细阅读发现它的运作原理是

.每个log操作,都会生成相关的字符串,最终调用write,写出到日志系统的文件描述符fd。

.进行rotate操作时,重新命名旧文件,保持旧文件的打开状态,然后打开新文件,将fd设置为新文件。

.接下来sleep 200ms,然后把close旧文件

那么轮替过程中,fd的值为fd_old或者fd_new,只要fd的读写是原子的,不会读取到非fd_old和fd_new的其他值即可(fd是int,这点可以做到)。write操作就没有问题

如果由于系统繁忙,fd读取为fd_old之后,走到操作系统的write之前,线程被切换,并且经过了200ms,那么fd_old就有可能会在sleep 200ms之后被关闭,那么write就可能失败。

因此这种做法是简洁的,能够应对绝大多数情况,但并非安全,而且切换时需要sleep 200ms也是个让人头疼的问题。

借鉴leveldb的做法,加上posix上的dup2调用则可以完美的解决这个问题。

.轮替时,首先重命名旧文件,保持旧文件的打开状态,然后打开新文件。

rename(oldname, newname);
fd = open(oldname,...);

.使用dup2系统函数把fd_new复制到fd_old上

dup2(fd, fd_);

.关闭fd_new

close(fd);

其中dup2是原子操作,它会关闭fd_old并且把fd_old也指向fd_new打开的文件。因此fd_old这个文件描述符总是保持打开状态,并且值不变,但是前后指向了不同的文件。另一边write也是个原子操作,它与dup2不会交叉进行,因此保证了日志系统的正确性。

详情参见开源库handy中的logging.h和logging.cc,里面一部分代码采用了C++11的语法

https://github.com/yedf/handy/tree/master/handy

handy的日志系统中,日志要做的内容就是使用snprintf格式化要输出的内容,然后调用write,没有多余的工作,因此做到了简洁高效

通过前面介绍的原理同时实现了无锁的线程安全,和日志轮替

每次日志的输出都write,即使程序崩溃,日志也已经到了操作系统层,不会丢失,易于调试问题

当然高效与及时保存有一定的冲突,如果缓存多条数据然后合并write能够提升一定的性能,但这里我选择简洁与易用

handy的日志系统性能测试可以参见项目examples下的log-bench.cc,在我笔记本电脑上的虚拟机的压力测试中,输出文件为/dev/null时,能够达到75w/s的qps

PS:handy的日志轮替中,对lastRotate_的读取和修改并非原子类型,可能会导致多轮替一次,解决方法为使用C++11中的原子类型,或者就容忍了(多轮替一次会在后续的操作中失败,仅仅多输出了一条信息到标准错误)。

 本文用菊子曰发布

C++ 高性能无锁日志系统的更多相关文章

  1. 高性能无锁队列 Disruptor 初体验

    原文地址: haifeiWu和他朋友们的博客 博客地址:www.hchstudio.cn 欢迎转载,转载请注明作者及出处,谢谢! 最近一直在研究队列的一些问题,今天楼主要分享一个高性能的队列 Disr ...

  2. DIOCP开源项目-Delphi高性能无锁队列(lock-free)

    最近想在DIOCP中加入任务调度线程,DIOCP的工作线程作为生产者(producer)将接受到的数据对象,投递到任务调度线程中,然后统一进行分配.然而这一切都需要一个队列, 这几天都在关注无锁队列. ...

  3. BP-Wrapper:无锁竞争的缓存替换算法系统框架

    BP-Wrapper:无锁竞争的替换算法系统框架 最近看了一个golang的高性能缓存ristretto,该缓存可以很好地实现如下功能: Concurrent High cache-hit ratio ...

  4. HAProxy + Keepalived + Flume 构建高性能高可用分布式日志系统

    一.HAProxy简介 HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代 理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案.HAProxy特别适用于那些负载特大的web站点, ...

  5. 基于无锁队列和c++11的高性能线程池

    基于无锁队列和c++11的高性能线程池线程使用c++11库和线程池之间的消息通讯使用一个简单的无锁消息队列适用于linux平台,gcc 4.6以上   标签: <无>   代码片段(6)[ ...

  6. php的高性能日志系统 seaslog 的安装与使用

    一.什么是日志系统    一般用于记录系统运行时的信息,一般分为三类:系统日志,应用程序日志,安全日志.日志功能不能影响用户的正常使用. 二.为什么需要日志功能    1.了解系统运行情况    2. ...

  7. EasyDarwin开源流媒体服务器高性能设计之无锁队列

    本文来自EasyDarwin团队Fantasy(fantasy(at)easydarwin.org) 一. EasyDarwin任务队列实现 EasyDarwin的任务队列是通过OSQueue类来组织 ...

  8. 【转载】scribe、chukwa、kafka、flume日志系统对比

    原文地址:http://www.ttlsa.com/log-system/scribe-chukwa-kafka-flume-log-system-contrast/ 1. 背景介绍许多公司的平台每天 ...

  9. scribe、chukwa、kafka、flume日志系统对比 -摘自网络

    1. 背景介绍许多公司的平台每天会产生大量的日志(一般为流式数据,如,搜索引擎的pv,查询等),处理这些日志需要特定的日志系统,一般而言,这些系统需要具有以下特征:(1) 构建应用系统和分析系统的桥梁 ...

随机推荐

  1. 学习AOP之透过Spring的Ioc理解Advisor

    花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...

  2. C语言 · 时间转换

    问题描述 给定一个以秒为单位的时间t,要求用"<H>:<M>:<S>"的格式来表示这个时间.<H>表示时间,<M>表示分 ...

  3. Gradle配置APK自动签名完整流程

    转载请注明出处:http://www.cnblogs.com/LT5505/p/6256683.html 一.生成签名 1.命令行生成签名,输入命令keytool -genkey -v -keysto ...

  4. CSS3 3D立方体效果-transform也不过如此

    CSS3系列已经学习了一段时间了,第一篇文章写了一些css3的奇技淫巧,原文戳这里,还获得了较多网友的支持,在此谢过各位,你们的支持是我写文章最大的动力^_^. 那么这一篇文章呢,主要是通过一个3D立 ...

  5. Win10 IIS本地部署网站运行时图片和样式不正常?

    后期会在博客首发更新:http://dnt.dkill.net 异常处理汇总-服 务 器 http://www.cnblogs.com/dunitian/p/4522983.html 启用关闭win功 ...

  6. CSS HTML元素布局及Display属性

    本篇文章主要介绍HTML的内联元素.块级元素的分类与布局,以及dispaly属性对布局的影响. 目录 1. HTML 元素分类:介绍内联元素.块级元素的分类. 2. HTML 元素布局:介绍内联元素. ...

  7. 学习ASP.NET Core,怎能不了解请求处理管道[2]: 服务器在管道中的“龙头”地位

    ASP.NET Core管道由注册的服务器和一系列中间件构成.我们在上一篇中深入剖析了中间件,现在我们来了解一下服务器.服务器是ASP .NET Core管道的第一个节点,它负责完整请求的监听和接收, ...

  8. SDWebImage源码解读 之 UIImage+GIF

    第二篇 前言 本篇是和GIF相关的一个UIImage的分类.主要提供了三个方法: + (UIImage *)sd_animatedGIFNamed:(NSString *)name ----- 根据名 ...

  9. 【干货分享】流程DEMO-人员调动流程

    流程名: 调动 流程相关文件: 流程包.xml 流程说明: 直接导入流程包文件,即可使用本流程 表单:  流程:  图片:3.png DEMO包下载: http://files.cnblogs.com ...

  10. Linux课堂笔记(一)

    一.Linux应用领域及版本介绍. 1.服务器.嵌入式.桌面应用等. (1)在服务器领域中,需要安全和稳定,特别是越老的内核版本越安全.越稳定. (2)Linux主要分内核版和发行版. 内核版本2.6 ...