我很惊讶我无法找到更多关于此的信息,但唉,我仍然找不到答案。我们最近转换为 AWS,将我们简单的网站迁移到更强大、更可靠的系统。目前让我感到困惑的是在分布式系统上管理 cron 作业,当该 cron 作业被推送到环境中的每个实例时。
这是用例:
背景
设置
我们正在运行一个传统的 LAMP 堆栈。可能是第一个问题,但这就是我们遇到的问题。
数据库表
table1
- id int(11)
- start date
- interval int(11) (number of seconds)
table2
- id int(11)
- table1_id int(11)
- sent datetime
目标
目标是脚本每天运行一次并检查以下内容:
- 当前日期已过
table1.start
table1.start
< 当前日期table1.interval
> 0- 今天正好是一个完整的间隔(如果间隔是 7 天 [以秒为单位] 并且它是第 6 天,则会失败)
- 今天没有条目,
table2
并且table2.sent
与table2.table1_id
之前的检查相匹配。
如果所有这些检查都通过,我们在 table2 中为每个具有间隔的 table1 插入一个条目。这也意味着我们根据表 2 中的数据发送电子邮件。
问题
本质上,我们有两个查询,由上述块表示。问题在于,在分布式系统上,每个实例将同时运行 cron(或彼此相隔几毫秒)。table2
没有“事务”的概念,因此如果一个实例在其他实例运行第一个查询之前没有机会插入,每个实例都会发送一封电子邮件。
解决方案???
我已经对此进行了大量研究,但我想出的唯一可能的解决方案如下:
Cron 实例
设置一个负责运行 cron 作业的独立实例。虽然这肯定会(据我所知)工作,但对于一项成本不高且最多每天只需要运行一次的工作来说,这是非常昂贵的。
PHP 调度程序
将 cron 设置为定期运行充当调度程序的 PHP 脚本。这是我们在研究表明这对于我们有限的时间和金钱来说是最简单的路线之后要走的路线。我遇到的问题是,这似乎只是将并发问题从消耗作业转移到了调度作业。您何时安排作业,以便不会从运行 cron 的每个实例同时安排多个作业?
这种方法似乎也很“笨拙”(借用我朋友最喜欢的一句话),我不得不同意。
交易
尽管我对此进行了相当多的研究,但始终通过数据库上的原子事务来解决并发问题,但据我所知,这在 LAMP 中并不容易实现。但也许我错了,我很高兴被证明是这样。
最后
因此,如果有人可以帮助我解决这个问题,我将不胜感激。也许我的谷歌搜索技能已经生疏了,但我无法想象我是唯一一个遭受这项(可能很简单)任务的人。