【问题标题】:Is transaction really required in a distributed counter?分布式计数器中真的需要事务吗?
【发布时间】:2019-06-08 14:19:58
【问题描述】:

根据firestoredocumentation

事务是对一个或多个文档的一组读写操作。

还有:

客户端离线时交易会失败。

现在firestore的限制是:

在 Cloud Firestore 中,您大约每秒只能更新一次单个文档,这对于某些高流量应用程序来说可能太低了。

因此,当流量高时使用云功能和运行事务来增加/减少计数器将会失败。

所以他们讨论了使用distributed counters的方法。

根据分布式计数器的算法:

  • 创建分片
  • 随机选择一个分片
  • 运行事务以增加/减少计数器
  • 获取所有分片并聚合 结果显示计数器的值

场景:
考虑您有一个计数器,当添加文档并且该计数器显示在 UI 中时,该计数器将被更新。现在对于良好的用户体验,当网络离线时我无法阻止用户界面。因此,即使客户端离线,我也必须允许创建/更新文档,并在客户端在线后同步这些更改,以便其他所有监听这些更改的人都能收到正确的计数器值。

现在当客户端离线时事务会失败。 所以我的问题为了获得最佳用户体验(即使离线)是:

  1. 您真的需要事务来增加计数器吗?我知道 事务确保写入是原子的,并且要么 成功/不成功并防止部分写入。但到底是什么 当他们离线失败时?我在想也许可以将它们写入本地缓存并在网络重新上线后同步它。

  2. 这应该通过客户端 SDK 还是通过云功能来完成?

【问题讨论】:

    标签: firebase transactions google-cloud-firestore counter


    【解决方案1】:

    你真的需要一个事务来增加一个计数器吗?

    绝对是的!因为我们正在创建可在多用户环境中使用的应用程序,所以事务是强制性的,因此我们可以提供一致的数据。

    但是离线失败有什么意义呢?

    当网络连接中断(用户设备上没有网络连接)时,不支持离线使用事务。这是因为事务绝对需要与服务器进行往返通信,以确保事务中的代码成功完成。因此,交易只能在您在线时执行。

    这应该通过客户端 sdk 还是通过云功能来完成?

    请注意,适用于 Android 的 Firestore SDK 具有默认启用的 local cache。根据Firestore offline persistence的官方文档:

    对于 Android 和 iOS,默认情况下会启用离线持久性。要禁用持久性,请将 PersistenceEnabled 选项设置为 false。

    因此,如果服务器上没有更新,所有读取操作都将来自缓存。所以 Firestore 提供了这个功能来处理离线数据。

    您还可以在 Cloud Function 中编写一个函数,在添加新文档时递增计数器或在删除文档时递减计数器。

    我也建议你看看:

    因此,您也可以考虑为此使用 Firebase 实时数据库。 Cloud Firestore 和 Firebase 实时数据库可以很好地协同工作。

    编辑:

    即使设备处于离线状态,它也允许人们对答案进行投票。网络上线后,同步到服务器并更新计数器。有没有办法在设备离线时在 Firestore 中执行此操作。

    默认情况下也会发生这种情况。因此,如果用户在离线时尝试添加/删除文档,每个操作都会添加到队列中。用户重新连接后,离线时所做的每项更改都会在 Firebase 服务器上更新。换句话说,所有查询都将在服务器上提交。

    只有在收到更改时才会触发云功能,并且只有在设备在线时才会发生。

    是的,没错。一旦设备重新获得网络连接,就会在数据库中添加/删除文档,此时函数会触发并增加/减少计数器。

    编辑2:

    假设我做了大约 100 次离线操作,那会不会在设备上线时对云功能造成负担?您对此有何看法?

    脱机时,尚未同步到服务器的待处理写入将保留在队列中。如果您在没有联机同步的情况下执行了太多的写入操作,那么该队列将快速增长,并且不仅会减慢写入操作,还会减慢您的读取操作。所以我建议使用这个数据库来实现它的在线功能。

    关于这 100 次离线操作的云功能,不会有任何问题。 Firebase 服务器可以很好地处理并发操作。

    【讨论】:

    • 好吧,总结一下,您建议在实时数​​据库而不是 firestore 上托管计数器,还建议使用云 fns 来增加/减少实时数据库中的计数器。我的理解是否一样正确?
    • 是的,没错。我建议您在 Firebase 实时数据库中托管计数器,因为它比 Cloud Firestore 中便宜。是的,您可以编写一个与用户设备无关的函数。一切都在服务器端完成。
    • 问题是如何在设备离线时提供良好的用户体验。例如让我们采取堆栈溢出。即使设备处于离线状态,它也允许人们对答案进行投票。网络上线后,同步到服务器并更新计数器。有没有办法在设备离线时在 Firestore 中执行此操作。只有在收到更改时才会触发云功能,并且只有在设备在线时才会发生。
    • 参考这个Once the device regains the network connection, the document is added/deleted from the database, moment in which the function fires and increases/decreases the counter.假设我离线操作了大约100次,那会不会在设备上线时对云功能造成负担?您对此有何看法?
    • 好吧,Alex,云函数的 python 运行时确实存在负载问题。存在云功能未执行或云功能已执行两次的情况。这已记录在案,idempotency 的概念用于确保它不会影响业务。例如,使用 Stripe API 向信用卡收费。我唯一担心的是管理这些关键计数器的云功能执行的可靠性。到目前为止,您是否遇到过任何此类问题并采取了一些措施?
    猜你喜欢
    • 2017-12-30
    • 2012-03-26
    • 2012-03-13
    • 2022-01-19
    • 2013-10-05
    • 2011-05-03
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    相关资源
    最近更新 更多