背景问题

在优化日志组件项目中有如下场景:两个进程,A、B进程往同一个文件写日志的时候,使用C语言的库函数写,fopen文件追加方式打开, fwrite等。如果每一次写的时候都强制fflush操作,则写的时序是正常的。如果不是每次fflush操作的时候,则会出现写入日志的时候的时序问题,即是A进程的一条日志没打完,B进程的日志中间插进来了。

问题分析

原子性

  • 系统调用
    先从最基本的系统调用说起,磁盘IO效率的简单分析,该篇的问题2中提到,如果是系统调用,多进程需要保证写磁盘有序,则需要open的时候使用O_APPEND选项,其本质是open的时候,写磁盘的时候会锁住文件的inode节点,全局唯一,所以进程间可以实现互斥。

  • 库函数IO
    对于C语言的库函数而言,它在系统调用的上层,做了一层缓冲。之所以自己做一层缓冲,是为了提升IO效率,在用户空间就对数据进行缓冲,最终使用合并写操作,以提升IO的效率。而多进程同时写文件的时候,由于flush的时机,由库函数自动决定,因此,多进程状态下,存在刷新操作的非原子性问题。

追问

库函数的追加写不是通过O_APPEND方式打开的吗?为什么这里刷新操作为什么不是原子的, 底层不是通过锁定innode方式实现的吗?

Write原子性

  • 系统调用原子性
    O_APPEND进行open的文件而言,系统调用,它能够保证原子性,在系统调用的过程之中,不会有其他系统调用打断它

  • 写数据的原子性
    这里有个非常重要的概念,write函数原型如下:ssize_t write(int fd, const void *buf, size_t count);它有个返回值,它表示此次调用成功写入了多少个字节。在这些成功写入的字节中,它是原子的。并不是你写1G缓冲,write就给你保证这1G数据就原子性写入磁盘,不要太天真!

flush的非原子性

通过上面的分析,我们知道,flush操作的时候,缓冲区中的数据,它是调用write系统调用来写磁盘,写入的数据能保证原子性。但是,但是,这里的缓冲区数据,它未必能够保证一次性全部写完。即是A、B进程都有1K字节缓冲区,调用write一次写1K字节,可能返回500字节,那此时,B进程可以调用write写入500字节,A再写完剩下的500字节,再写剩下的B进程的500字节。这种情况下,那么,flush操作则会导致日志的乱序,原因找到。

如何优化

对于日志组件而言,在多进程并发写的情况下,一个优化方式无非就是合并写,但这里利用库函数做合并,flush的时候存在并发问题。如何解决?

解决方案

  • 手动加锁刷新
    通过手动刷新代替库函数的自动刷新,在缓冲区满之前,手动加上进程锁进行刷新操作。例如:满100条日志的时候,就手动刷新一次。但这里会存在一个问题,当流量特别小的时候,日志会特别久才出来一次,何解?且看方案二
  • 定时线程刷新
    每一个进程创建一个分离线程,进行定时刷新,例如:每一秒钟刷新一次。这样就能解决小流量调试的时候,日志的查看及时度问题

多进程写同一个日志并发问题分析相关推荐

  1. 多进程写同一个日志文件时如何确保每条日志不与其他日志重叠

    背景/ write + O_APPEND 可以实现多进程写相同日志不交叉 我们有多个进程,往同一个文件写日志.当然希望能每条日志边界清晰,既不与其他日志重叠,也不与其他日志交叉.为了达到这个目的,最直 ...

  2. logback多进程写同一日志文件导致日志混乱问题

    记录一次logback多进程写同一日志文件导致日志混乱问题 参考该博客解决问题

  3. Python 多进程向同一个文件写数据

    1.遇到的问题: 之前,因为考虑到Python多进程可以充分利用CPU核数,提高程序的效率,所以就使用多进程写文件.但是向同一个文件写入数据的时候,由于多进程是并发进行,操作系统中会不清楚到底要写入哪 ...

  4. jvm根节点枚举、安全点、安全区域、记忆集、卡表、写屏障、并发的可达性分析

    讲具体的实现之前,先说说几个和这些垃圾回收器息息相关的一些知识点,可以有一个更好的理解 1.根节点枚举 也就是可达性分析算法从GC Roots集合中找引用链的过程,可作为GC Roots的节点主要在全 ...

  5. python多进程读写文件_Python多进程写文件时的一些探究

    问题提出 在没有并发控制的情况下,Python多进程向同一个文件写数据(限制单次写入数据大小)是安全的吗? 这里的安全是指: 不会有进程的日志丢失(被覆盖) 两次写入的数据不会相互混着输出(譬如A进程 ...

  6. 自动化日志收集及分析在支付宝 App 内的演进

    背景 结合<蚂蚁金服面对亿级并发场景的组件体系设计>,我们能够通盘了解支付宝移动端基础组件体系的构建之路和背后的思考,本文基于服务端组建体系的大背景下,着重探讨"自动化日志手机与 ...

  7. 支付宝客户端架构分析:自动化日志收集及分析

    小蚂蚁说: <支付宝客户端架构解析>系列将从支付宝客户端的架构设计方案入手,细分拆解客户端在"容器化框架设计"."网络优化"."性能启动优 ...

  8. 支付宝客户端架构分析:自动化日志收集及分析 1

    小蚂蚁说: <支付宝客户端架构解析>系列将从支付宝客户端的架构设计方案入手,细分拆解客户端在"容器化框架设计"."网络优化"."性能启动优 ...

  9. ClickHouse 在日志存储与分析方面作为 ElasticSearch 和 MySQL 的替代方案

    2018年,我写过一篇关于Clickhouse的文章,这段内容在互联网上仍然很流行,甚至被多次翻译.现在已经过去两年多,同时 Clickhouse 的开发节奏仍然活跃: 上个月有 800 个合并的 P ...

最新文章

  1. 取值范围_从int取值范围谈起
  2. [转载]日历设计之重复事件规则设计
  3. svn 迁移到 git 仓库并保留 commit 历史记录
  4. java学习笔记(二) ----基本数据类型应用
  5. Python3.5入门到项目实战(104天课程)
  6. 无盘服务器 双镜像盘,镜像(无盘柜)-双活集群解决方案
  7. 设计模式之-命令模式(Command Pattern)
  8. Java集合框架练习-计算表达式的值
  9. [jQuery基础] jQuery节点操作
  10. vue在html中写style,vue开发之style(六)(CSS页面布局之样式、背景、文字)
  11. 关于二叉树,你该了解这些!
  12. 保证可见性_十年程序员浅谈并发的原子性、可见性、有序性
  13. Android蓝牙完全学习手册
  14. vim 设置配色方案
  15. 修改elementUI 表格透明度,字体颜色
  16. 转型实践|产品设计从青铜到王者—青铜篇
  17. 桃子CCD视觉高速喷射点胶机,用它你就会爱上它
  18. CS客户端单元测试(1) 开始
  19. 万测试验机软件,万测关注检查井盖质量检测
  20. 解决CSR 8510 A10蓝牙适配器驱动安装不正常问题

热门文章

  1. Springboot——mybatis配置
  2. 魅族手机里的便签怎么导出转移到新的手机上?
  3. 汶川地震牵动我全家人的心
  4. java蘑菇岛种子_比蘑菇岛更稀有的“蘑菇陆地”见过么?输入MC种子即可找到
  5. 计算机定时关机教程,1分钟学会 如何让电脑定时关机,定时开机!
  6. 通信大小端_Motorola和Intel
  7. 如何看待网易强制取消所有用户魔兽世界游戏时间
  8. python设备分组(部门分组等)功能设计
  9. 【历史上的今天】9 月 7 日:世界上第一部电子电视;惠普联合创始人出生;上亿美国人隐私信息泄露
  10. [经验教程]手机上微信新消息不提示也不显示微信消息通知怎么办?