如何使用Firebase云功能避免可能的竞争情况? [英] How do you avoid a possible race condition with firebase cloud functions?

查看:51
本文介绍了如何使用Firebase云功能避免可能的竞争情况?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有由Firestore数据库写入触发的云功能.它执行异步操作(从某些第三方API提取数据),这可能需要很长时间,而可能不会.完成后,它将结果写入搜索结果"字段.

I have a cloud function that is triggered by a Firestore database write. It does an async operation (fetch data from some 3rd party API's) that may take a long time, might not. When it's finished, it writes the result to a 'search result' field.

在某些竞争情况下,较新的触发器的结果将被较旧的操作所覆盖,而较早的操作将在稍后完成此操作.如何在Firebase云功能和Firestore的上下文中解决此问题?

There's a possible race condition where the result from a newer trigger gets overwritten by an older operation that finishes this later. How should I solve this problem in the context of Firebase cloud functions and Firestore?

推荐答案

通常,这里有两种方法:

In general there are two approaches here:

  1. 确保您的操作是幂等的
  2. 确保您的操作检测到冲突的更新并重试

确保您的操作是幂等的

这通常是最可扩展的并且在结构上最简单.当您在相同的输入上执行相同的幂等运算时,其结果相同.这意味着该操作是否执行了多次都没有关系,因为结果将是相同的.

Ensure your operations are idempotent

This is often the most scaleable and architecturally simple. When you perform the same idempotent operation on the same input, it has the same result. This means that it doesn't matter if the operation is performed multiple times, as the result will be the same.

关于数组和集合的Firestore文档 .想象一下,您正在用类别标记博客文章.一个简单的模型是:

A good example of this is in the Firestore documentation on arrays and sets. Imagine that you're tagging blog posts with categories. A naïve model for this would be:

{
    title: "My great post",
    categories: [
        "technology",
        "opinion",
        "cats"
    ]
}

但是现在想象一下,两个用户几乎同时在同一条帖子中标记了关于猫的帖子.您可能会得到

But now imagine that two users are tagging the same post as being about cats at almost the same time. You might end up with

{
    title: "My great post",
    categories: [
        "technology",
        "opinion",
        "cats",
        "cats"
    ]
}

显然不是您想要的.但是由于数据结构允许,所以可能会发生这种情况.此处的理想解决方案是使用一种使这种情况不可能实现的数据结构:在其中添加cat是幂等运算的数据结构.用数学术语来说,这是一个集合,在Firestore中,您可以将其建模为:

Which is clearly not what you wanted. But since the data structure allows it, this may happen. The ideal solution here is to use a data structure that makes this impossible: a data structure where adding cat is an idempotent operation. In mathematical terms this would be a set, and in Firestore you'd model that as:

{
    title: "My great post",
    categories: {
        "technology": true,
        "opinion": true,
        "cats": true
    }
}

现在在此结构中,将cats设置为true的频率无关紧要,结果将始终相同.

Now in this structure, it doesn't matter how often you set cats to true, the result will always be the same.

有时不可能(或不可行)使您的操作成为幂等.在这种情况下,您还可以考虑使用比较设置策略.

Sometimes it isn't possible (or feasible) to make your operations idempotent. In that case, you can also consider using a compare-and-set strategy.

例如,假设第三方API以某种方式更改了数据,并且您只想在未修改数据库中原始数据的情况下将结果写回数据库.在这种情况下,您需要在函数中执行以下步骤:

For example, say that the 3rd party API changes the data in some way, and that you want to only write the result back to the database if the original data in the database is unmodified. In that case you'll want to take these steps in your function:

  1. 读取原始数据
  2. 使用数据调用第三方API
  3. 等待结果
  4. 开始交易
  5. 再次加载原始数据
  6. 如果数据已被修改,请返回到#2
  7. 如果未修改数据,请写入第三方API的结果

这种类型的比较设置操作实际上就是Firebase的实时数据库实现事务的方式,第三方API"是您的应用程序事务处理程序.

This type of compare-and-set operation is actually how Firebase's Realtime Database implements transactions, with the "3rd party API" being your applications transaction handler.

您可能会看到,第二种方法比具有幂等运算的方法更为复杂.因此,在可能的情况下,我总是会推荐这种方法.

As you can probably see this second approach is more complex than the approach with idempotent operations. So when possible, I'd always recommend that approach.

这篇关于如何使用Firebase云功能避免可能的竞争情况?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆