line = json.dumps(rec, ensure_ascii=False) + '\n'
fd = os.open(path, os.O_WRONLY | os.O_APPEND | os.O_CREAT, 0o644)
os.write(fd, line.encode('utf-8'))
os.close(fd)

四个 worker 往同一个日志写,grep 出来的行里出现 order=8821 user=3ERROR db timeout,两条记录粘在一起。按行解析的脚本直接抛异常。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:单个 write 在 O_APPEND 下是原子的,但一行日志往往被拆成多次 write,中间被别的进程插进来就交错。文本模式还会先攒缓冲,一次 flush 的边界和行边界并不一致。

「并发写文件交错」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。监控和日志的时间要对上,时区不一致会多绕很大一圈。

临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

处理上按这个顺序:每个进程写自己的文件 用 pid 或 worker 编号区分;必须合写就在应用层加文件锁或走 syslog;一次 write 拼完整行再发 不要分多次;写完后按行做格式校验 发现粘连就告警。

确认没问题再收工,压测十分钟后日志每行都能被 json.loads 解析 粘连行数为 0。

作者 9823189