我很惊讶没有找到更多相关信息,但我仍然找不到答案。我们最近转换到AWS,将我们的简单网站移动到一个更强大和可靠的系统上。目前令我困扰的是在分布式系统上管理cron作业,当该cron作业被推送到环境中的每个实例时。
以下是用例:
背景
设置
我们正在运行传统的LAMP堆栈。可能是第一个问题,但这就是我们得到的。
数据库表
以下是用例:
背景
设置
我们正在运行传统的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
匹配。
如果所有这些检查都通过,我们将为具有间隔的每个 table1 插入一个条目到 table2。这也意味着我们根据 table2 中的数据发送电子邮件。
问题
基本上,我们有两个查询,由上述块表示。问题在于,在分布式系统上,每个实例将同时运行 cron(或在彼此之间的几毫秒内)。没有“事务”的概念,因此如果一个实例没有机会在其他实例运行第一个查询之前插入到 table2
,则每个实例都会发送电子邮件。
解决方案???
我已经进行了相当多的研究,但我想到的唯一潜在解决方案如下:
Cron 实例
设置单个、独立的实例负责运行 cron 作业。虽然这肯定会(就我所看到的)起作用,但对于一个不是非常昂贵且只需要每天最多运行一次的作业来说,这是非常昂贵的。
PHP 调度程序
将 cron 设置为定期运行充当调度程序的 PHP 脚本。这是我们在研究后要走的路线,因为它对于我们有限的时间和金钱来说似乎是最简单的。我遇到的问题是,这似乎只是将并发问题从消耗作业转移到调度作业。您何时安排作业,以便每个实例运行 cron 时不会同时安排多个作业?
这种方法也似乎非常“笨拙”(借用我的朋友最喜欢的词),我必须同意。
事务
尽管我已经进行了相当多的研究,并且并发始终通过数据库上的原子事务解决,但据我所知,在 LAMP 上实现这一点并不容易。但也许我是错的,如果能证明我错了,我会非常高兴。
最后
如果有人可以帮助我解决这个问题,我将非常感激。也许我的 Google 搜索技巧正在变得生疏,但我无法想象自己是唯一遭受这种(可能简单)任务的人。