一次操作系统缓存,引发的运维事件

网友投稿 868 2022-10-03

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

一次操作系统缓存,引发的运维事件

虽然在很多公司批处理已经成了稀罕物,但是在我们公司还依然是主流的背锅侠。之所以说背锅侠,做得好没人知道,做的差了所有人都知道了。

我们公司的批处理系统由几十台高性能服务器构成,每天处理上百万个批处理作业,服务器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);

这两种方式都可以将所有的缓存强制写到磁盘上。既然问题找到了,赶紧加上这行代码,果然后续再也木有出现漏数的问题了。

妈妈再也不用担心我运维了。

随手分享,点个“在看”,为老司机加个油!

上一篇:知识点 | MySQL的运维神器之 Percona Toolkit 介绍
下一篇:六个人如何运维一万台服务器?
相关文章

 发表评论

暂时没有评论,来抢沙发吧~