防止多个 cron 作业同时运行

防止多个 cron 作业同时运行

我的服务器在午夜运行多个 cron 作业。每个作业都会创建某些内容的备份,方法是创建一个 tarball 并使用 进行压缩xz

由于xzCPU 和内存占用很大,我为每个作业添加了随机延迟,这样它们“不应该”相互干扰。但这种情况时有发生,导致服务器负载过重。

假设:

  • 根据我的流量,午夜是进行备份的最佳时间 - 但仍然有流量(这就是为什么我想避免过度负载)
  • 每个面向公众的应用程序都与其自己的备份作业相关联,并且这些作业是解耦的(它们彼此不知道) - 因此我无法将备份 cron 作业合并为单个作业,因为我需要这种粒度
  • 我无法对每个应用程序的开始时间进行硬编码,因为这会增加维护工作量——要将应用程序添加到服务器(通过 ansible),我只需部署它并将备份 cron 作业(计划在午夜执行)放入其中/etc/cron.d/,作业开始前的随机延迟通常就足够了
  • 我通过 - 对作业进行了一些限制tar ... | pv --rate-limit ... | xz ...,但尽管这样可以减少每个作业的负载,但也会减慢每个作业的速度,从而增加多个作业同时运行的可能性(这些作业加在一起可能会消耗 100% 的 CPU)

一种可能的解决方案是让每个作业创建一个临时文件来表示它很忙,然后将其删除。问题是,如果作业检测到此文件,它会做什么?休眠?休眠多长时间?我可以使用 让它休眠一段时间at,但如果我的备份脚本出现问题,我可能会有大量的作业相互竞争。另一个维护难题。

那么,通常如何解决这个问题呢?基本上,一种安排相关 cron 作业的简单方法,不会让它们互相干扰,也不需要微调启动时间。

答案1

随机分布开始时间有利于避免高峰时段,使用 Ansible 很容易做到。但并不能真正确保资源可用于维持多个并发压缩作业。有几种方法可以进行低影响备份,请考虑其中的一些或全部。

通过基于 CPU 进行节流的程序运行命令列表。例如,GNU并行 --limit 100% 仅当平均负载低于 CPU 数量时才会运行。

每个作业都会尝试获取少量锁中的一个。例如使用flockutil-linux、Python 或 Perl。这似乎很简单,但维护多个锁会很麻烦。我认为内置作业管理的包装器命令更强大,例如 GNU parallel。

评估您的压缩算法。規模很现代,而且速度很快,只是内存稍微大了一点。

将备份工作分散到更多时间。考虑一下 00:00 到 03:00 是否适合您的性能和备份要求。

添加 CPU。调整峰值容量可能成本较高,但可以允许更多压缩线程。

将备份完全卸载到另一台主机。获取存储阵列或基于云的磁盘快照。呈现给另一台主机。从那里备份。

答案2

使用壳运算符例如,要在午夜运行,command1command2不管前者的输出如何,请使用:

0 0 * * * command1 ; command2

command2或者,只有成功完成时才可以运行command1(返回退出状态为零):

0 0 * * * command1 && command2

command1当 的失败可能意味着 存在潜在故障而阻碍 的成功时,后者或许更有用command2

答案3

看一下@JohnMahowald 的回答,其中有很多选项,包括巧妙地处理争用。

我决定做的是,不将备份作业添加到/etc/cron.d,而是将它们添加到自定义 cron 目录,例如/etc/cron.backupjobs/

然后我将添加一个“主”作业,用于/etc/cron.d/运行/etc/cron.backupjobs/ 依次

相关内容