如何为聊天应用程序分片数据实时数据库?

时间:2021-07-24 10:16:07

标签: firebase firebase-realtime-database sharding

我正在构建一个聊天应用程序并想使用实时数据库。 我希望我的数据库达到配额 200k 同时连接。

所以我已经阅读了关于扩展和分片数据的 documentation

但是我不明白如何为聊天应用程序处理这个问题。 假设我有一个 groups 引用,其中包含每个组内用户的 ID 以及该组的消息。

如果我想扩展,我需要创建一个新的数据库实例并在那里开始写入组,因为第一个数据库可能有超过 200k 的同时连接。

这意味着用户可能属于多个数据库中的 groups,这似乎已经很奇怪了,也不是一个好主意。

所以我想知道:

  • 如何对 groups 引用进行分片?
  • 我如何(甚至应该)让用户根据他们所属的 groups 连接到多个数据库?

这似乎是一种非常复杂的做事方式......我是不是没有正确理解这一点?

1 个答案:

答案 0 :(得分:4)

我确信有很多方法可以对数据库进行分片,但我是这样做的。这涉及在创建新聊天时选择分片。对于这个答案,我们假设有 4 个用户:U1、U2、U3 和 U4,以及 2 个分片(不包括默认):shard1 和 shard2。

每当用户创建新聊天时,选择一个分片并为该聊天创建一个新节点。您应该将用户的聊天列表与分片 ID 一起存储在其他地方,默认数据库实例似乎非常适合,但 Firestore 也可以使用。因此,包含聊天信息的对象将如下所示:

{
  chatID: "c40f15af19a94b6f84117747337b9f7a",
  createdBy: "U1",
  users: ["U1", "U2", "U3"],
  shardId: "shard2"
}

现在您拥有聊天 ID 列表及其分片,因此只需连接您的听众即可。同样,这取决于预期的行为是什么。就我而言,我只需要收听用户选择的数据(即活动聊天)。

尝试在所有分片之间平均分配聊天。一个聊天数量最少的活动(您必须将每个分片创建的聊天数量存储在其他地方,如默认分片)(或类似 Round Robin 之类的东西可能有用。同时,考虑创建聊天的用户.

enter image description here

在创建新聊天时增加分片中存在的聊天数可能是一种好方法。

最后,我认为这只是关于您如何将聊天分成碎片,并且您可以使用许多算法。拥有包含分片名称的用户聊天列表似乎是一种简单的方法,如上所述。我个人更喜欢 Firestore 存储聊天列表,这样可以更轻松地根据聊天的创建者、用户 U2 所在的聊天等进行查询。

首选使用 Cloud Function(或您的服务器)创建新聊天,因此没有人可以通过对应用程序进行逆向工程来向单个数据库分片发送垃圾邮件。

这样,您的所有消息都将存储在实时数据库中,但聊天的基本信息将存储在 Firestore 中(不是必需的,但更易于查询聊天)。当用户打开聊天应用时,加载他们所属的聊天:

这是一个示例 Firestore 文档:

enter image description here

const db = firebase.firestore()
// loading user's chats
const chatsSnapshot = await db.collection("chats").where("members", "array-contains", "myUID").get()

const chatsInfo = chats.map((c) => ({...c.data(), id: c.id}))


// Realtime DB shards
const shards = {
  shard1: firebase.database(app1),
  shard2: firebase.database(app2),
  shard3: firebase.database(app3)
}

// Run a loop on chatsInfo and render chats to your app
for (const chat of chatsInfo) {
  // Limit to first N messages if necessary
  const chatRef = shards[chat.shardId].ref(chat.id);
  chatRef.on('value', (snapshot) => {
    const data = snapshot.val();
    // Render messages
  });
}

您不需要加载我上面显示的所有聊天记录。仅为活动聊天加载消息。