0

的背景

我们的客户使用他们设定每日预算的服务。这是一项预付费服务,我们每天从用户的预算中分配特定金额。

表:

  • 预算——我们每天可以花多少钱
  • - 客户实际余额
  • money_allocated - 从今天可以花费的中扣除的金额(基于预算

有一个 cron 作业每隔几分钟运行一次并检查:

  • 如果用户在给定的一天有money_allocated
  • 如果money_allocated >= budgets(用户可以在白天增加预算)

在第一种情况下,我们分配每日预算的全部金额,在后者中 - 预算与当天已分配金额之间的差额(在这种情况下,我们在同一天的money_allocated中创建附加记录)。

分配有两个阶段——在第一轮中,我们添加一行状态为“待处理”(已请求分配),另一个 cron 检查所有“待处理”分配,如果用户有足够的钱,则将钱从money转移到money_allocated 。这会将状态更改为“已完成”。

问题

我们有一个应用程序服务器集群(在 NLB 下),并且上面的 cron 作业在每个服务器上运行,这意味着可能会意外地多次分配资金(或者如果我们实施错误的“已分配”触发器,则根本不分配)。

我们的选择包括:

  • 仅在一台服务器上运行 cron 作业 - 没有冗余、客户投诉和失败造成的金钱损失
  • 在money_allocated上添加一个唯一索引,类似于 (client_id, date, amount) - 如果客户在一天内将预算翻倍或多次增加相同的金额,则不会为给定的一天分配更多的钱

有一个选项可以记录预算中的每个变动,并将所有分配链接到“当天的第一次分配”或“预算更改(id xxx)”(也将其添加到唯一索引)。然而,这看起来不够性感。

还有其他选择吗?任何建议将不胜感激!

4

1 回答 1

2

好的,所以我最终在集群的一个实例上运行它。如果您使用 Amazon AWS 并且处于类似情况,以下是其中一个选项。

在每台机器上,在您的 cron 作业代码的开头,执行以下操作:

  • 调用describe_load_balancers(AWS API),解析响应以获取所有实例的列表/数组
  • Get http://169.254.169.254/latest/meta-data/instance-id- 这将返回发送请求的机器的实例 ID
  • 如果收到的实例 ID 在所有实例的列表/数组中是 #1 - 继续,如果不是 - 退出

此外,请务必在短时间内自动替换此负载均衡器下的不健康实例,因为它会describe_load_balancers返回健康和不健康实例的列表。如果实例 #1 出现故障,您最终可能会暂时没有完成工作。

于 2012-11-25T00:13:16.743 回答