在Cloud Firestore中使用顺序ID的限制

4

我在 stackoverflow 的帖子(链接 这里)中读到:

使用可预测的(例如顺序的)文档 ID,会增加命中后端基础架构热点的几率。这降低了写操作的可扩展性。

如果有人能更好地解释使用顺序或用户提供的 ID 时可能出现的限制,那就太好了。


1
你有没有阅读那里的答案并点击进入Google的google-cloud-firestore-discuss邮件列表上的讨论?我认为不会有比那更详细的了。 - Doug Stevenson
哦,不小心跳过了那个!谢谢。 - pariola
1个回答

8

Cloud Firestore通过将key范围分配给多台机器来进行水平扩展。当单个机器的负载超过特定阈值时,它会将正在服务的范围分裂并分配到2台机器上。

假设您刚开始使用Cloud Firestore写入数据,这意味着一台服务器当前正在处理整个范围。

当您使用随机Id编写新文档时,当我们将范围分裂成2个时,每台机器最终的负载将大致相同。随着负载的增加,我们继续分裂成更多的机器,每台机器都得到大致相同的负载。这样可以实现良好的扩展性。

当您使用连续Id编写新文档时,如果超出了单个机器可以处理的写入速率,系统将尝试将范围分裂为2个。不幸的是,一个部分没有负载,而另一个部分则有全部负载!这并不适合扩展,因为您永远无法让多台机器处理您的写入负载。

在单个机器运行的负载超过最佳处理能力时,我们称之为“热点”。连续的Id意味着我们无法扩展以处理更多负载。顺便说一句,这个概念也适用于索引条目,这就是为什么我们警告连续的索引值(如now 时间戳)。

那么,负载到了多少才算太大?通常情况下,我们说单个机器可以处理500次写入/秒,尽管这将根据许多因素而自然变化,例如您正在编写的文档大小、事务数量等。

考虑到这一点,您会发现较小、更一致的工作负载并不是问题,但如果您想要根据流量进行扩展,则连续的文档id或索引值自然会限制您与数据库中的单台机器保持同步。


这个内容应该真的写在文档里。我刚刚花了很长时间重构我的实现,使用顺序 ID(App 实例 ID + "_" + 本地 SQLite 行 ID)代替生成的 ID,结果现在才发现这个问题。 - Actine
很遗憾听到这个消息 @Actine。我们在最佳实践中提到了这一点: https://cloud.google.com/firestore/docs/best-practices - 你是否在文档中碰巧看到过它,但并不清楚,还是完全没有找到该部分? - Dan McGrath
我从来没有看过 cloud.google.com 的文档,只看 Firebase 的文档。 - Actine
@Actine - 这里也有:https://firebase.google.com/docs/firestore/best-practices。因为它在可折叠菜单中有点隐藏,所以给我们的技术写作团队留个便条吧。 - Dan McGrath
1
哦,对不起,不知怎么错过了。无论如何,回退并不是问题。虽然我不认为我会遇到那些缩放问题。但这也让我想知道,如果我将我的数据结构化为每个用户子集合,例如 /users/<uid>/tasks/<task id>,其中每个用户基本上只能访问自己的任务,那么性能影响会是什么?当涉及到这一点时,Firestore 会首先在用户之间分割数据,还是分割每个用户的子集合? - Actine
@DanMcGrath,您能否详细说明一下这部分内容:“顺便说一下,这个概念也适用于索引条目,这就是为什么我们警告顺序索引值(如当前时间戳)的原因。”特别是与这篇文章(https://buildkite.com/blog/goodbye-integers-hello-uuids)有关的部分,该文章指出:“非时间顺序的UUID [..] 不是连续的。[..] 这些值在数据库索引中不会聚集在一起,[..] 插入操作将在随机位置执行。这种随机插入可能会对常见的索引数据结构(如B树及其变种)的性能产生负面影响。” - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接