-1

如果我们的数据库中修改了某些特定数据,我们的 API 需要将数据发送到 Zapier。

例如,我们有一个公司表,如果名称地址字段被修改,我们会触发 Zapier 钩子。

有时我们的 API 会在几分钟内收到多个更改请求,但我们不想多次触发 Zapier 钩子(因为它非常昂贵),所以我们在每个修改请求上调用一个setTimeout()(并覆盖现有的),用一个延迟。setTimeout5000ms

它工作正常,即使我们在此5000ms期间收到来自客户端的大量修改请求,也没有多次 Zapier 挂钩调用。

现在 - 由于我们的流量正在增长 - 我们想在一些负载均衡器后面设置多个 node.js 实例。

但是在这种情况下,不同的 Node.js 实例不能使用 - 并覆盖 - 同一个setTimeout实例,这会导致很多无用的 Zapier 调用。

你们能否帮助我们,如何解决这个问题 - 同时保持可扩展性?

4

1 回答 1

1

如果你想在不同的实例之间保持状态,你应该考虑,从基础设施的角度来看,一些锁定机制,比如 Redis。每当你想运行 Zapier 调用时,如果没有激活锁,你在 Redis 上设置一个,所有其他调用都不会被触发,因为它被锁定,每当setTimeout回调运行时,你禁用锁。请注意 Redis 可能会成为SPOF,我不知道您将服务托管在哪里,但这可能是需要考虑的重要一点。

编辑:

Redis 上的锁可能引用了您要更新的最后一条信息。因此,在第一个请求中,您将数据设置为保存在 Redis 上,等待 5 秒,然后更新。如果在该时间范围内进行了任何修改,它将存储在 Redis 上,这样您只会每隔 5 秒更新一次,不过您需要在此处添加一些额外的逻辑。例子:

function zapierUpdate(data) {

  if (isLocked()) {

    // Locked! We will update the data that needs to be saved on the
    // next setTimeout callback
    updateLockData(data);

  } else {

    // First lock and save data.
    lock(data);
    // and update in 5 seconds
    setTimeout(function(){
      // getLockData fetches the data on Redis and releases the lock
      var newData = getLockData();
      // Update the latest data that might have been updated.
      callZapierNow(newData);
    },5000);

  }

}
于 2015-12-17T12:19:59.510 回答