【问题标题】:Unreliable Google Firebase transactions不可靠的 Google Firebase 交易
【发布时间】:2020-03-16 17:12:41
【问题描述】:

在我的(非常简化的)模型中,我有用户、帐户和 account_types。每个用户可以拥有每个 account_type 的多个帐户。创建 TT 类型的帐户后,我将更新该对象的“用户”字段,以便保留拥有该类型帐户的用户以及他们拥有的此类帐户的数量。

users: {
  some fields
},
accounts: {
  userID: UU,
  type: TT
},
account_type: 
  users: { UU: 31 }
}

我使用帐户的 onCreate 和 onDelete 云触发器来更新 account_type 对象。由于可以同时创建多个帐户,因此我必须使用事务:

exports.onCreateAccount = functions.firestore
    .document('accounts/{accountID}')
    .onCreate((account, context) => {
      const acc_user = account.data().userID;
      const acc_type = account.data().type;
      return admin.firestore().runTransaction(transaction => {
        // This code may get re-run multiple times if there are conflicts.
        const accountTypeRef = admin.firestore().doc("account_types/"+acc_type);
        return transaction.get(accountTypeRef).then(accTypeDoc => {
          var users = accTypeDoc.data().users;
          if (users === undefined) {
            users = {};
          }
          if (users[acc_user] === undefined) {
            users[acc_user] = 1;
          } else {
            users[acc_user]++;
          }
          transaction.update(accountTypeRef, {users: users});          
          return;
        })
      })
      .catch(error => {
        console.log("AccountType create transaction failed. Error: "+error);
      });
    });

在我的测试中,我首先使用一些数据填充数据库,因此我还添加了一个用户和 30 个相同类型的帐户。使用本地模拟器,这工作得很好,在添加结束时,我看到 account_type 对象包含计数器为 30 的用户。但是当部署到 Firebase 并运行相同的功能时,计数器会小于 30。我的怀疑是因为 Firebase 速度慢得多,事务需要更长的时间,所以它们中的更多是冲突和失败的,最终根本不执行。交易失败文档 (https://firebase.google.com/docs/firestore/manage-data/transactions) 说:

“事务读取了在事务之外修改的文档。在这种情况下,事务会自动再次运行。事务会重试有限次。”

所以我的问题:

  1. “有限”是什么意思?
  2. 有什么方法可以控制这个数字?
  3. 如何确保我的事务在某个时间点被执行并且不会像那样被丢弃,从而使我的数据保持一致?
  4. 关于为什么我在部署到云时没有得到正确结果的任何其他想法?

【问题讨论】:

  • 我测试了您的云功能,确实有时您需要等待几分钟才能正确更新计数器。我们清楚地看到计数器更新是在“波”中执行的。你应该看看分布式计数器:firebase.google.com/docs/firestore/solutions/…
  • 另请注意,您可能会在 Cloud Functions 控制台中收到与此类似的错误消息:Error: quota exceeded (Quota exceeded for quota group 'FunctionCallsNonbillable' and limit 'Function invocations per 100 seconds' of service 'cloudfunctions.googleapis.com' for consumer 'project_number:xxxxxx'.); to increase quotas, enable billing in your project at https://console.cloud.google.com/billing?project=xxxxxx. Function cannot be executed.。所以你可能需要切换到 Blase 计划。

标签: arrays firebase google-cloud-firestore transactions google-cloud-functions


【解决方案1】:

“有限”是什么意思?

这与“无限”相反。它将重试不超过设定的次数。

有什么方法可以控制这个数字?

除了修改SDK的源代码,没有。 SDK 本身会公布一个特定的数字,因为它可能会发生变化。

我怎样才能确保我的交易在某个时候被执行并且不会像那样被丢弃,所以我的数据是一致的?

检测错误并在您的应用中重试。如果您没有看到交易失败并出现错误,则说明没有任何问题。

关于为什么我在部署到云时没有得到正确结果的任何其他想法?

由于我们无法看到您究竟在做什么来触发该功能,也没有具体的预期结果可比较,所以真的不可能说。

【讨论】:

  • 仔细查看日志发现确实有错误:“Error: 10 ABORTED: Too much content on these documents. Please try again.”当我发现此错误时,重试事务的正确方法是什么?
  • 我发现这可能有用:stackoverflow.com/questions/52339969/…
猜你喜欢
  • 2020-03-21
  • 1970-01-01
  • 2017-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-08
相关资源
最近更新 更多