首页 > 解决方案 > 分布式计数器真的需要事务吗?

问题描述

根据firestore文档

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

还:

客户端离线时事务将失败。

现在firestore的限制是:

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

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

所以他们讨论了使用分布式计数器的方法。

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

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

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

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

  2. 这应该通过云功能的客户端 sdks 来完成吗?

标签: firebasetransactionsgoogle-cloud-firestorecounter

解决方案


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

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

但是当他们离线失败时有什么意义呢?

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

这应该通过云功能的客户端 sdks 来完成吗?

请注意,适用于 Android 的 Firestore SDK 具有默认启用的本地缓存。根据有关Firestore 离线持久性的官方文档:

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

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

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

我还建议你看看:

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

编辑:

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

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

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

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

编辑2:

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

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

对于这 100 个离线操作的 Cloud Functions,不会有任何问题。Firebase 服务器可以很好地处理并发操作。


推荐阅读