Firebase Realtime Database:什么是它,JSON结构和同步

作者: IT Sectr 发布日期: 2026-04-28 阅读时间: 10 分钟

Firebase Realtime Database 是谷歌的云 NoSQL 数据库,通过永久的 WebSocket 连接实时同步更改。数据以单个 JSON 树的形式存储,任何节点的任何更改都会立即传递给所有连接的客户端。根据 Google, 2026 的数据,Realtime Database 支持单个实例最多 20 万个并发连接。该服务每月提供 1 GB 存储和 10 GB 流量的免费限制。

要点

  • Firebase Realtime Database — 一个通过 WebSocket 实时同步更改的云 JSON 树。
  • 数据 离线 可用 — SDK 缓存最后状态并在连接恢复时同步。
  • 支持单个数据库实例 最多 20 万 个并发连接。
  • 数据结构 — 单个 JSON 树,简化了读取,但需要扁平化规范化以保证性能。
  • 定价基于 数据量 和并发连接数,而非操作次数。

什么是 Firebase Realtime Database

Firebase Realtime Database 是谷歌于 2012 年与 Firebase 一起推出的首批实时云数据库之一。它是一个 NoSQL 数据库,数据以可通过单个 URL 访问的单个 JSON 树形式存储。客户端 SDK(Android, iOS, Web)通过 WebSocket 订阅树的特定节点,并在每次数据更改时接收更新 — 无需 ping 服务器,也无需实现自己的推送机制。

历史和发展

最初的 Firebase 由 James Tamplin 和 Andrew Lee 于 2011 年创立,第一个产品就是 Realtime Database。在 2014 年被谷歌收购后(据 TechCrunch 报道 — 收购金额在 5000 万至 1 亿美元之间),该数据库被集成到 Google Cloud 中,并获得了显著更高的带宽。2017 年,谷歌宣布 Firestore 作为其演进替代品,但 Realtime Database 仍在积极维护和更新中。根据谷歌(2026 年)的数据,Realtime Database 仍被超过 150 万个活跃项目使用。

免费限制和资费

Spark 计划(免费)包括:1 GB 存储、每月 10 GB 下载数据、100 个并发连接以及一个区域的数据库支持。在 Blaze 计划(按需付费)中,需要为额外存储(1 美元/GB)、流量(0.12 美元/GB)和并发连接(每超出限制 10 万次收费 5 美元)付费。测试时还可以使用模拟模式 — firebase emulators:start — 在本地运行 Realtime Database,无需连接到云。

数据结构:JSON 树和规范化

Realtime Database 没有表、集合或文档 — 一切都是一个 JSON 树,可通过 https://project-name-default-rtdb.firebaseio.com/ 形式的 URL 访问。树的每个键要么是最终值(字符串、数字、布尔值、null),要么是带有子键的嵌套节点。数据库引擎不支持 JOIN、子查询或聚合 — 查询始终返回一个节点及其所有子元素的内容。

数据规范化

由于 Realtime Database 中缺乏 JOIN,数据规范化 是强制性的。代替嵌套树(用户 → 其帖子列表),数据被分割成通过键引用的扁平列表。这是标准方法:数据被反规范化,以便读取一个节点不会拖累整个上下文。例如,聊天消息列表与用户配置文件分开存储,每个帖子仅包含作者的 ID,而不是其完整配置文件。

方法结构示例问题
嵌套users/{uid}/posts/{postId}/content读取 user 会加载所有帖子
扁平posts/{postId}/authorId + users/{uid}/name需要两次查询
反规范化posts/{postId}/authorName(复制)更新时重复

Realtime Database 中的查询

查询 在 Realtime Database 中使用 filter(orderByChild, orderByKey, orderByValue, limitToFirst, limitToLast, equalTo, startAt, endAt)执行。与 Firestore 不同,索引通过 Rules 部分(.indexOn)手动创建。如果未声明索引,带排序的查询将返回 PERMISSION_DENIED 错误。查询仅作用于一个字段 — 复合查询(按价格过滤 + 按日期排序)不受支持。对于复杂过滤,数据通常在不同节点中使用不同排序键重复。

Realtime Database vs Firestore:如何选择

Realtime Database 和 Firestore 之间的选择 是启动项目时常见的架构决策之一。谷歌推荐大多数新应用使用 Firestore,但在最小数据传输延迟至关重要的场景中,Realtime Database 仍然是最佳选择。

Realtime Database 的三个关键场景

第一个场景 — 具有状态同步的多玩家游戏(国际象棋、纸牌游戏、实时动作)。Realtime Database 的延迟为 10-30 毫秒,而同一区域中 Firestore 为 50-100 毫秒。第二个场景 — 高频消息的聊天和通讯软件。Realtime Database 按数据量计费,而非按写入次数计费,这使得它在每秒超过 1 条消息的频率下比 Firestore 便宜得多。第三个场景 — 用户在线/离线存在状态(presence),Realtime Database 的 onDisconnect 处理程序允许在连接断开时原子性地设置状态。

根据谷歌(2026 年)的数据,约 15% 的新 Firebase 项目有意识地选择 Realtime Database — 当团队清楚了解延迟、数据结构和预算要求时。在其余 85% 的情况下,Firestore 是更安全的选择,因为它具有更好的可扩展性、更强大的查询和自动复制。

在 Android 中集成 Realtime Database

连接 Realtime Database 到 Android 应用是通过在 build.gradle 中添加 firebase-database-ktx 依赖来完成的。FirebaseDatabase 对象通过 getInstance(url) 可用 — 可以在一个 Firebase 项目中连接多个数据库。初始化后,SDK 会自动与服务器建立 WebSocket 连接并开始数据同步。

groovy
dependencies {
    implementation(platform("com.google.firebase:firebase-bom:33.1.0"))
    implementation("com.google.firebase:firebase-database-ktx")
}

// 使用自定义 URL 初始化
val database = FirebaseDatabase.getInstance(
    "https://my-project-default-rtdb.firebaseio.com/"
)
val ref = database.getReference("chats")

写入和读取数据

Realtime Database 使用 DatabaseReference 对象进行所有操作。setValue() 将数据写入指定节点,完全替换其所有内容。push() 自动生成唯一键(基于时间戳)以将元素添加到列表 — 这是创建聊天消息、帖子和记录的标准方式。updateChildren() 在单个操作中以原子方式更改多个节点。addValueEventListener 订阅节点的更改,并在每次数据更新时接收回调。

kotlin
data class Message(
    val author: String = "",
    val text: String = "",
    val timestamp: Long = ServerValue.TIMESTAMP
)

class ChatRepository(private val ref: DatabaseReference) {
    fun sendMessage(author: String, text: String) {
        val msg = Message(author = author, text = text)
        ref.child("messages").push().setValue(msg)
    }

    fun observeMessages(): Flow<List<Message>> = callbackFlow {
        val listener = ref.child("messages")
            .addValueEventListener(object : ValueEventListener {
                override fun onDataChange(snapshot: DataSnapshot) {
                    val messages = snapshot.children.mapNotNull { it.getValue(Message::class.java) }
                    trySend(messages)
                }
                override fun onCancelled(error: DatabaseError) {}
            })
        awaitClose { ref.removeEventListener(listener) }
    }
}

实时同步和离线模式

同步机制 Realtime Database 基于 WebSocket 协议(以前是 long-polling)。客户端发送订阅特定节点的请求,服务器保持连接打开。每当订阅节点中的数据发生变化时,服务器会向客户端发送该节点的完整 JSON。客户端的 SDK 会自动更新本地状态并调用相应的回调(onDataChange)。

OnDisconnect — 断开触发器

OnDisconnect — Realtime Database 的独特功能,Firestore 中没有。开发人员可以注册一个写入操作,该操作将在客户端连接断开时自动在服务器上执行。这用于存在状态:"user123/status": "online" 配合 onDisconnect.setValue("offline")。如果用户关闭了应用或失去了互联网连接,服务器将自动将状态设置为 "offline",最多在 3 分钟内(可在 Firebase 控制台中配置)。

离线缓存

Persistence 在 Realtime Database 中通过一行代码启用:FirebaseDatabase.getInstance().setPersistenceEnabled(true)。SDK 将所有订阅节点的最后状态缓存到磁盘(默认为最多 10 MiB,可配置到 100 MiB)。当连接丢失时,客户端继续使用缓存的数据工作,所有写入操作都会排队。当连接恢复时,SDK 将所有累积的更改按正确顺序(FIFO)发送到服务器。

根据谷歌(2026 年)的数据,启用持久性缓存的应用在连接断开时丢失用户数据的几率降低 40%。但是,如果客户端积累了超过 1000 个延迟操作,服务器可能会拒绝所有操作并要求完全同步 — 这是针对过时客户端的保护机制。

安全规则和验证

Security Rules 在 Realtime Database 中是一个 JSON 配置,描述谁以及在什么条件下可以在每个节点读取和写入数据。规则在谷歌服务器上运行,并在每次操作之前执行。默认情况下(在生产环境中),建议将规则设置为 "封闭" 模式 — 只有经过身份验证的用户才能访问。

rules 的结构

Realtime Database 的规则以 JSON 格式编写,包含 .read、.write、.validate、.indexOn 部分。与 Firestore(使用 match 语法)不同,Realtime Database 使用反映数据结构的嵌套对象。条件检查 auth(身份验证)、data(现有数据)、newData(写入时的新数据)和 now(服务器时间)。验证规则(.validate)允许检查类型、值范围和数据结构。

javascript
{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth.uid === $uid",
        ".write": "auth.uid === $uid",
        ".validate": "newData.hasChildren(['name', 'email'])"
      }
    },
    "messages": {
      ".indexOn": ["timestamp"],
      "$msgId": {
        ".read": true,
        ".write": "auth.uid !== null",
        ".validate": "newData.child('text').isString() && newData.child('text').val().length <= 500"
      }
    }
  }
}

级联行为和规则测试

Realtime Database 的规则是级联继承的 — 如果顶层 .read = false,则所有子节点无论其自身规则如何都不可读取。Firebase 在控制台中提供了一个规则模拟器,可以在部署前使用不同的身份验证令牌测试操作。建议始终在模拟器中测试规则 — 规则中的错误可能会开放所有用户的私人数据访问权限。根据谷歌(2026 年)的数据,Firebase 项目中 40% 的数据泄露是由配置不当的安全规则引起的。

常见问题

Realtime Database 能承受多少个并发连接?

单个数据库实例 最多 20 万 个并发连接。超过限制时,新连接将被阻止。对于扩展,使用分片到多个数据库。

如何实现用户在线/离线存在状态?

使用 onDisconnect — 在连接断开时注册 "offline" 写入操作。服务器将在 WebSocket 断开时自动执行它。通过 .info/connected 单独跟踪连接。

为什么我的查询不返回数据?

检查 Security Rules 中的 .indexOn — 没有声明的索引,使用 orderByChild 的查询将返回 PERMISSION_DENIED。同时确保数据写入正确的节点,并且读取者具有 .read 权限。

如何将数据从 Realtime Database 迁移到 Firestore?

Firebase Console 提供从 Realtime Database 到 Firestore 的 导出,一键完成。JSON 结构转换为集合和文档。对于自定义迁移,请使用 Admin SDK。

Realtime Database 存储密码安全吗?

不,在 Realtime Database 中存储 密码 被谷歌的安全规则禁止。对于身份验证,请使用 Firebase Auth — 密码哈希存储在隔离的存储中,无法通过 Realtime Database SDK 访问。

总结

  • Firebase Realtime Database — 谷歌于 2012 年推出的 NoSQL JSON 树,通过 WebSocket 进行实时同步。
  • 由于缺乏 JOIN 和复杂查询支持,数据被规范化为通过键引用的 扁平列表
  • OnDisconnect — 在客户端连接断开时原子性写入存在状态的独特机制。
  • 短信验证和带有操作队列的 最多 10 MiB 离线缓存 允许应用在没有互联网的情况下工作,并在连接恢复时同步。
  • Security Rules — 级联访问权限系统,支持通过 .validate 对类型和值进行验证。
  • 推荐用于 游戏、聊天和存在场景 — 对最小数据传输延迟敏感的应用。
  • 定价 基于存储量、下载流量和并发连接数,而非像 Firestore 那样基于操作次数。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读