Firestore 每秒向一个集合写入 500 多次

Firestore 500+ Writes Per Second to One Collection

Firestore 的限制为每秒 500 次写入

"a collection in which documents contain sequential values in an indexed field"

https://cloud.google.com/firestore/quotas#writes_and_transactions

在什么情况下我可以将 ONE 集合中的写入限制提高到每秒 10,000 次?

假设我使用 Best Practices 使文档 ID 在整个键范围内相对均匀地分布。

A) 如果文档不包含任何顺序值怎么办?

例如我在每个文档中的唯一字段如下。

B) 如果文档包含顺序字段,但我从未按该字段进行查询怎么办?

C) 如果文档包含顺序字段,but I turn off indexing 到字段 B 中的日期怎么办?

C) 第 2 部分 - 如果我关闭对该日期字段的索引(并且这消除了每秒 500 次的限制),如果我将字段 C 随机添加到collection? 将这个带有字段 C 的文档破坏每秒 10,000 次写入集合的限制吗?因为现在 Firestore 必须担心任何新字段 C 的自动索引?

(然后每次您向该集合中的任何文档添加随机字段时是否都会发生这种情况,因此必须关闭对集合中每个可能字段的索引以消除 500ps 限制?)

每秒 500 次写入是对单个服务器可以处理的内容的保守估计。由于 Cloud Firestore 对文档和索引存储进行水平行分片;这意味着使用顺序 ID 编写的文档或顺序添加的索引条目将由单个服务器处理。将这些放在一起(每台服务器 500 次写入 + 由 1 台服务器处理的顺序更新)就是给你的限制。

当您拥有分布良好的数据时,我们的水平行分片可以将工作负载拆分到许多服务器中。对于原生模式下的 Cloud Firestore,这将一直有效,直到您达到我们实时系统的上限,即大约 10K writes/second。对于Datastore模式的Cloud Firestore,没有实际限制,只要您给我们提个醒(客户可以超过1Mwrites/second)

简而言之,A)和C)将受到模式上限(10K或可用容量)的限制。 B) 将受到单个服务器可以处理的负载的限制。

对于 C2),如果您只是将其添加到单个文档中,则不会有任何影响。该限制完全基于传入负载及其分配到的服务器。

对于社区:Firestore 更新了他们的文档以包含更多关于每秒写入 500 次限制的原因的详细信息,以及关于如何克服它的建议解决方案。

https://firebase.google.com/docs/firestore/solutions/shard-timestamp

解决方案

  1. timestamp 字段旁边添加一个 shard 字段。为分片字段使用 1..n 个不同的值。这将集合的写入限制提高到 500*n,但是 您必须聚合 n 个查询
  2. 更新您的写入逻辑,为每个文档随机分配一个 shard 值。
  3. 更新您的查询以聚合分片结果集。
  4. 禁用 shard 字段和 timestamp 字段的单字段索引。
  5. 删除现有的包含timestamp字段的复合索引。 创建新的复合索引以支持您更新的查询。 索引中字段的顺序很重要,shard 字段必须在时间戳字段之前。 包含 timestamp 字段的任何索引还必须包含shard 字段。

警告(文档中未突出显示)

他们没有在文档中明确指出,但是 分片可能会增加您必须执行的读取次数。正如您在第 1 步中看到的那样,您必须跨分片聚合。

例如示例中有 3 个分片,限制为 5。查询 returns 最多 15 个文档,但您只想要 5。所以最后它把它切回 5

如果您有 [10] 个分片(每秒 5000 次写入)并且希望限制为 [50],这将尤其成问题。当您只想要 [50].

时,您将汇总 [500] 个文档

了解限制顺序索引字段的写入

The limit on the write rate for sequential indexed fields comes from how Cloud Firestore stores index values and scales index writes. For each index write, Cloud Firestore defines a key-value entry which concatenates the document name and the value of each indexed field. Cloud Firestore organizes these index entries into groups of data called tablets. Each Cloud Firestore server holds one or more tablets. When the write load to a particular tablet becomes too high, Cloud Firestore scales horizontally by splitting the tablet into smaller tabletsand spreading the newtablets` across different Cloud Firestore servers.

Cloud Firestore places lexicographically close index entries on the same tablet. If the index values in a tablet are too close together, such as for timestamp fields, Cloud Firestore cannot efficiently split the tablet into smaller tablets. This creates a hot spot where a single tablet receives too much traffic, and read and write operations to the hot spot become slower.

By sharding a timestamp field, you make it possible for Cloud Firestore to efficiently split workloads across multiple tablets. Although the values of the timestamp field might remain close together, the concatenated shard and index value give Cloud Firestore enough space between index entries to split the entries among multiple tablets.