【问题标题】:Q: Firebase Extension Limit Child Nodes问:Firebase 扩展限制子节点
【发布时间】:2022-02-09 23:40:17
【问题描述】:

我正在运行一个具有 160k DAU 的 Firebase 应用,这是一款在线回合制游戏,它使用 RTDB 在玩家之间发送更新。在最繁忙的时间,我的数据库负载峰值约为 60%。

对我来说很长一段时间的问题是如何在比赛结束后“清理”比赛节点。当前结构:

root/games/$gameId

gameId 由主机在匹配过程中提供。之后,两个玩家都订阅这个节点并发送更新。

我可以做的是让 2 个客户端中的一个在游戏结束后删除节点,但这将是另一个(不可靠的)写入以增加数据库负载。我的主要目标是将“死游戏节点”保持在最低限度,从而降低存储成本(Blaze 计划)。我最近才知道这个扩展,但我很好奇我的“成本”是多少。

Q1:这个扩展的每个触发器都会算作对我的数据库的“写入”吗?鉴于一个实例每秒只允许 1000 次写入,这将进一步增加此计数(每秒会触发多次)。

Q2:在 youtube 信息视频中,它说使用自动生成的 ID“效果最好”,但它需要吗? https://www.youtube.com/watch?v=i_u_6RknUro

我知道这个扩展实际上只是一个云功能,但在我敢于使用它之前,我想知道它在幕后是如何工作的:)

感谢您的帮助:)

【问题讨论】:

    标签: firebase firebase-realtime-database


    【解决方案1】:

    所有 Firebase 扩展都是开源的,因此如果您想了解 Limit Child Nodes 扩展的工作原理,可以查看其installation page 中的source code 链接。

    那里的代码:

    export const rtdblimit = functions.handler.database.ref.onCreate(
      async (snapshot): Promise<void> => {
        logs.start();
    
        try {
          const parentRef = snapshot.ref.parent;
          const parentSnapshot = await parentRef.once("value");
    
          logs.childCount(parentRef.path, parentSnapshot.numChildren());
    
          if (parentSnapshot.numChildren() > config.maxCount) {
            let childCount = 0;
            const updates = {};
            parentSnapshot.forEach((child) => {
              if (++childCount <= parentSnapshot.numChildren() - config.maxCount) {
                updates[child.key] = null;
              }
            });
    
            logs.pathTruncating(parentRef.path, config.maxCount);
            await parentRef.update(updates);
            logs.pathTruncated(parentRef.path, config.maxCount);
          } else {
            logs.pathSkipped(parentRef.path);
          }
    
          logs.complete();
        } catch (err) {
          logs.error(err);
        }
      }
    );
    

    看起来像这个扩展:

    • 在列表中创建新的子节点时触发。
    • 然后读取整个父节点以确定有多少子节点。
    • 然后通过一次写入操作删除超过其最大值的任意数量的子代。

    这符合我对代码的回忆,因为我编写了它的第一个版本。 :)

    对于您的问题:

    Q1:这个扩展的每个触发器都会算作对我的数据库的“写入”吗?

    将子节点写入数据库时​​会触发 Cloud Functions。写入算作写入,触发器本身发生在带外。如果您阅读我链接的其余代码,您会发现它会在一次写入时删除超过最大值的所有子节点。

    Q2:在 youtube 信息视频中,它说使用自动生成的 ID“效果最好”,但需要吗?

    在没有排序条件的情况下读取节点 (const parentSnapshot = await parentRef.once("value")),然后从该列表的开头删除节点。所以它假设要删除的节点位于列表的开头,当这是按它们的键排序时。只要这也适用于您的数据,密钥来自哪里都没有关系。

    【讨论】:

    • 感谢@Frank van Puffelen 的详细回答!
    猜你喜欢
    • 2020-03-13
    • 2016-02-18
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多