利用多个数据库进行扩展

如需在 Firebase Realtime Database 中优化性能和扩大数据规模,最好的方法是将数据拆分到多个 Realtime Database 实例中,也称为数据库分片。除了负载均衡和性能优化之外,分片还让您可以灵活地扩容,不再受单个数据库实例限额的限制。

何时将数据分片

如果您要在以下情况下使用 Realtime Database,建议您最好将数据分片到多个数据库中:

  • 您希望将单个数据库实例的限额扩充到超过 20 万个并发连接、每秒 1,000 次写入操作或其他任何限额
  • 您有多个互不关联的数据集,并希望优化性能(例如,为各自独立、互不相关的用户组提供服务的聊天应用)。
  • 您希望在多个数据库之间均衡负载,以增加正常运行时间并降低单个数据库实例负载过高的风险。

如何进行数据分片

如需将数据分片,请按照以下步骤操作(后面有详细介绍):

  1. 根据您的应用的具体需求将数据映射到多个数据库。
  2. 创建多个数据库实例。
  3. 配置您的应用,使其连接到每个数据集所需的 Realtime Database 实例。

映射您的数据

在将数据映射到多个数据库时,请尽量满足以下条件:

  • 每个查询仅针对单个数据库实例来执行。Realtime Database 不支持跨数据库实例的查询。
  • 数据库实例之间不存在共享或重复的数据(或只有极少的共享或重复数据)。
  • 无论何时每个应用实例都只连接到一个数据库。

在映射数据时,您不妨考虑采用以下策略:

创建一个“主分片”

存储一个用来反映数据在各个数据库实例中的存储情况的映射。这样,您就能以编程方式查找与连接的客户端对应的数据库实例。请注意,与根据需要直接连接所需的特定数据库实例相比,此策略的开销可能会更大。

按类别或客户对数据分桶

将数据分别存储在多个独立数据库实例中,并按用户或数据类型进行分组。 例如,如果您要构建一个为多个组织提供服务的聊天应用,则可以为每个组织分别创建一个数据库实例,并将各个组织的所有聊天数据存储到各自对应的唯一数据库实例中。

在这种情况下,A 组织和 B 组织不共享数据,这些数据库实例中没有任何重复的数据,并且您只针对单个数据库实例执行查询。此外,每个组织中的用户只有在使用该聊天应用时才会连接到其组织的数据库。

这样,您便可以预先创建多个数据库实例,并使用组织的 ID 将某个团队映射到其数据库实例。例如,A 组织映射到 Realtime Database A。

您为应用映射数据的方式取决于具体的使用情形,上述条件和策略可以帮助您确定适合自己数据的方式。

创建多个 Realtime Database 实例

如果您使用的是 Blaze 定价方案,则可以在同一个 Firebase 项目中最多创建 1,000 个数据库实例。

在 Firebase 控制台中通过“数据库”部分的上下文菜单创建数据库

  1. Firebase 控制台中,前往开发 > 数据库部分中的数据标签页。
  2. Realtime Database 部分的菜单中选择创建新数据库
  3. 自定义数据库引用安全规则,然后点击知道了

您可以重复上述过程,根据自己的需要创建任意多个数据库实例。每个数据库实例都有自己的一组 Firebase Realtime Database Security Rules,因此您可以精细调整对自己数据的访问权限。

您可以通过 Firebase 控制台或使用 Realtime Database Management REST API 创建和管理数据库实例。

为每个实例修改和部署 Realtime Database Security Rules

确保您的 Realtime Database Security Rules 安全规则允许正常访问项目中的每个数据库实例。每个数据库都有自己的一套规则,您可以通过 Firebase 控制台或者使用 Firebase CLI 部署目标对其进行修改和部署。

  • 如需通过 Firebase 控制台修改和部署规则,请按以下步骤操作:

    1. 前往开发 > 数据库部分的规则标签页。
    2. 选择要修改的数据库,然后对规则进行修改。
  • 如需通过 Firebase CLI 修改和部署规则,请按以下步骤操作:

    1. 修改您数据库实例的规则文件中的规则(例如,foo.rules.json)。
    2. 创建并应用部署目标,以关联使用相同规则文件的数据库。例如:
      firebase target:apply database main my-db-1 my-db-2
      firebase target:apply database other my-other-db-3
    3. 使用部署目标更新 firebase.json 配置文件:

      {
        "database": [
          {"target": "main", "rules": "foo.rules.json"},
          {"target": "other", "rules": "bar.rules.json"}
        ]
      }
      
    4. 运行 deploy 命令:

      firebase deploy

确保始终通过同一工具修改和部署规则。通过 Firebase CLI 部署规则会覆盖您在 Firebase 控制台中所做的修改,而直接在 Firebase 控制台中修改规则会覆盖您近期通过 Firebase CLI 部署的更改。

将您的应用连接到多个数据库实例

使用数据库引用来访问存储在辅助数据库实例中的数据。 您可以根据网址或应用获取对特定数据库实例的引用。如果您不指定网址,则会获得对应用的默认数据库实例的引用。

Web

import { initializeApp } from "firebase/app";
import { getDatabase } from "firebase/database";

const app1 = initializeApp({
  databaseURL: "https://testapp-1234-1.firebaseio.com"
});

const app2 = initializeApp({
  databaseURL: "https://testapp-1234-2.firebaseio.com"
}, 'app2');

// Get the default database instance for an app1
const database1 = getDatabase(app1);

// Get a database instance for app2
const database2 = getDatabase(app2);

Web

const app1 = firebase.initializeApp({
  databaseURL: "https://testapp-1234-1.firebaseio.com"
});

const app2 = firebase.initializeApp({
  databaseURL: "https://testapp-1234-2.firebaseio.com"
}, 'app2');

// Get the default database instance for an app1
var database1 = firebase.database();

// Get a database instance for app2
var database2 = firebase.database(app2);
Swift
注意:此 Firebase 产品不适用于 App Clip 目标。
// Get the default database instance for an app
var ref: DatabaseReference!

ref = Database.database().reference()
// 通过网址获取辅助数据库实例 var ref: DatabaseReference! ref = Database.database("https://testapp-1234.firebaseio.com").reference()
Objective-C
注意:此 Firebase 产品不适用于 App Clip 目标。
// Get the default database instance for an app
@property (strong, nonatomic) FIRDatabaseReference *ref;

self.ref = [[FIRDatabase database] reference];
// 通过网址获取辅助数据库实例 @property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase databaseWithURL:@"https://testapp-1234.firebaseio.com"] reference];

Kotlin+KTX

// Get the default database instance for an app
val primary = Firebase.database.reference

// Get a secondary database instance by URL
val secondary = Firebase.database("https://testapp-1234.firebaseio.com").reference

Java

// Get the default database instance for an app
DatabaseReference primary = FirebaseDatabase.getInstance()
        .getReference();

// Get a secondary database instance by URL
DatabaseReference secondary = FirebaseDatabase.getInstance("https://testapp-1234.firebaseio.com")
        .getReference();

使用 Firebase CLI 时指定实例

使用 --instance 选项指定要为其运行 Firebase CLI 命令的 Firebase Realtime Database。例如,使用以下命令为名为 my-example-shard.firebaseio.com 的数据库实例运行性能分析器:

firebase database:profile --instance "my-example-shard"

优化每个数据库的连接

如果每个客户端都需要在一个会话期间连接到多个数据库,应仅在必要时连接到各个数据库实例,以减少各个数据库实例的并发连接数。

获取更多建议

如果您需要更多有关将数据分片到多个数据库实例的帮助,请通过我们的 Slack 频道Stack Overflow 与 Firebase 专家联系。