AIOps 一场颠覆传统运维的盛筵
868
2022-10-03
一次操作系统缓存,引发的运维事件
虽然在很多公司批处理已经成了稀罕物,但是在我们公司还依然是主流的背锅侠。之所以说背锅侠,做得好没人知道,做的差了所有人都知道了。
我们公司的批处理系统由几十台高性能服务器构成,每天处理上百万个批处理作业,服务器CPU和内存常年在80以上。所谓多行夜路,必遭鬼神。最近一个月,系统就遇到好几起怪事。
前些阵子,下游同学提着锅来,怒气道:“哥们,你的系统又双叒叕漏数。”
运维同事瞥了一眼怒气冲冲的同事,心里有点不爽:“你在逗我?”
“源系统有一千万条,你少加载了1000条。赶紧解决,否则你这系统没法用。”
“兄弟,别急。Let me look下作业的执行路径。”运维同事不慌不忙地打开作业调度系统。这是标准的作业流和程序,已经稳定运行好几年了,不应该有问题。
抽取成文件
加载入库
先通过“grep 数据 文件名”查下文件里面有没有漏掉的数据,
“oh my god,竟然还真有这数据。”
本着严于律己的原则,通过重跑看看某些特殊数据触发了作业程序的bug。这次重跑大法并不好用,重跑后的结果集里面没有缺少这1000条数据。看来不是特殊数据的问题,再阅读下代码简单的单线程程序,没啥明细的bug。
紧接着又对上游程序也检视了N次,没发现啥问题。N天尝试了N种方法,依然是木有结果,对方的领导已经开始敲桌子了。
“灵感,一切都是灵感”,运维同学提起如何发现问题的原因时如是说。那天早上,他被老板逼得不行,本着死马当活马医的想法,猜想这次问题是不是跨服务器导致的。果不其然,每次漏数都是上下游作业跑在不同的服务器上导致的。
跨服务器会有啥问题呢?再看看上游的代码,最重要的三行代码
os.write(data);
os.flush();
os.close();
上述代码生成完文件后,将数据从缓存刷到磁盘,然后关闭文件。存在问题唯一可能就是数据从缓存刷新到磁盘,真的会刷新到磁盘吗?
在linux系统中,一份文件分为三层
JVM
Linux
物理-文件
内存页-文件
缓存-文件
flush()操作只是将文件从JVM缓存刷新到了LINUX的内存页中,然后由Linux操作系统决定何时刷新到物理盘上。因而可能导致问题的原因就是B服务器在A服务器将脏页写到磁盘之前就运行了,导致从磁盘上看到的文件缺少了部分数据。
既然原因已经找到了,再看看FileOutputStream下有没有相应的方法可以解决,找来找去,发现了两种方式:
os.getFD().sync();
和
os.getChannel().force(true);
这两种方式都可以将所有的缓存强制写到磁盘上。既然问题找到了,赶紧加上这行代码,果然后续再也木有出现漏数的问题了。
妈妈再也不用担心我运维了。
随手分享,点个“在看”,为老司机加个油!
发表评论
暂时没有评论,来抢沙发吧~