在修改大文件时对其进行存档的最无副作用的方法

在修改大文件时对其进行存档的最无副作用的方法

我正在管理一个应用程序,该应用程序会在 Red Hat 服务器上的日志文件中生成大量数据(每天约 5G)。这个过程在一周内运行 24 小时,因此一天中没有时间不修改文件,尽管午夜时分添加到其中的信息并不是特别重要,所以如果我在这段时间内丢失几秒钟的数据也没关系。

为了每天对日志文件进行“安全”存档,我创建了一个脚本,它会在清晨的某个时间点执行以下操作:

  • 将文件复制到本地文件夹
  • 截断“活动”文件
  • tar+压缩副本
  • 将副本的 tar.gz 移动到我们的存档空间

以下是脚本本身,以防其中存在明显的问题:

DF=$(date +"%Y%m%d_%H%M%S")
TARGET="fixdata-logs-$DF"
cp -r ./fixdata/logs $TARGET

#Truncate the original log file
find ./fixdata/logs -name '*.log' -exec sh -c 'cat /dev/null >| {}' \;

#Zip the log files
tar -zcvf $TARGET.tar.gz $TARGET

#Delete the labelled copy
rm -rf $TARGET

#Archive files older tha 3 days
find . -type f -mtime +3 -name \*.gz -exec mv {} $ARCHIVE_DIR \;

(我理解有些数据可能会丢失,但是这个脚本运行的几秒钟的数据丢失并不重要。)

问题是,在此期间,应用程序经常报告与系统资源相关的错误。例如,其队列的心跳监视器经常无法产生规律的心跳。很明显,这个 copy->tar.gz->move 过程对服务器 IO 造成了足够大的影响,以至于影响了应用程序的行为。

我该如何减少此脚本的影响?完成时间并不重要 - 如果解决方案花费的时间更长但不会导致应用程序错误,那么这比快速的解决方案更好。还有其他方法值得我考虑吗?

为了完整起见,我考虑了以下内容,但有疑问:

  • 跳过复制部分并直接使用 tar:但我担心如果在繁忙时修改文件,tar 会出现问题。
  • 先复制到存档文件夹,然后再 tar - 如果压缩是在不同的磁盘上完成的,那么 IO 影响可能较小?我担心我们使用的存档空间不适合执行输入/输出磁盘操作(如压缩),因为我不认为它是传统的随机存取磁盘。我也不确定复制到不同的物理磁盘是否会使情况变得更糟,因为我原本以为操作系统有一些巧妙的方法来制作本地副本,而无需物理读取文件中的所有字节。不幸的是,我的 *nix 技能在这里帮不上忙。
  • 等到周末:不幸的是,服务器上的磁盘空间不足以在归档前容纳一周的数据。当然我可以要求增加磁盘空间,但首先我想看看是否有更合理的解决方案。

答案1

你可以这样做显著地通过不执行复制+截断来减少 I/O 负载。相反,重命名文件,然后,如果进程保持日志文件描述符打开,则执行任何必要的操作以使其回收其日志描述符(通常发送HUP是执行此操作的规范方法)。如果程序还没有此功能,则对其进行修补以使其具备此功能。

通过这样做,您将不会有在同一介质上复制的 I/O 开销(即同时读取+写入),然后截断(这可能是也可能不是一个很大的负载,取决于您的文件系统),并且然后读取 tar/compress 并写入 load 以制作档案。

重命名日志文件后,您可以随意执行 tar/compress/whatever 操作。为了进一步减少 I/O 负载,请考虑将 tar/compress 的写入端直接写入存档存储 - 虽然您的存档存储可能不是典型的随机访问设备,但它仍会采用即时压缩的直接数据流(使用正确的 CLI 工具,即使 S3 也可以做到这一点)。

另一件需要考虑的事情与上述情况正交,那就是使用ionice。通过以 运行程序ionice -c 3 <command>,您可以将进程的 I/O 优先级降至“仅空闲”——也就是说,如果有任何事物系统上其他需要执行 I/O 操作的地方,你的程序就会受到影响。这是一个好主意,但是如果你有一个繁重的 I/O 系统(你的程序可能需要故事完成,因为它很少有 I/O 时间)。如果您已经执行了过多不必要的 I/O,则将其设置为“仅空闲”优先级将使问题变得更加严重。

我也非常怀疑空闲调度不会相当按照说明操作;我曾看到,当“仅空闲”程序运行时,与“仅空闲”进程未运行时相比,其他(“尽力而为”调度的)进程的性能略有下降。我怀疑这是因为当“仅空闲”进程正在执行 I/O 操作时,程序请求 I/O,在“尽力而为”进程的 I/O 操作开始之前,会有一个延迟,直到 I/O 完成。也就是说,这仍然比“仅空闲”进程以“尽力而为”优先级运行时好得多,但它并不是乍一看似乎的神奇万能解决方案。

答案2

查看 rhel 中提供的 logrotate linux 实用程序,它具有压缩、copytruncate 和各种其他选项,并且它还处理应用程序正在使用的日志文件,就像您拥有的一样。您还可以尝试使用 ssd 磁盘并将数据复制到应该是最快的磁盘上,尽管它仍将使用 cpu,但只要您不使用 usb,就可以消除对慢速磁盘的 io。

相关内容