实时架构
Realtime 是一个全球分布的 Elixir 集群。客户端可以通过 WebSockets 连接集群中的任何节点,并向集群中连接的任何其他客户端发送消息。
🌐 Realtime is a globally distributed Elixir cluster. Clients can connect to any node in the cluster via WebSockets and send messages to any other client connected to the cluster.
Realtime 是用 Elixir 写的,它会编译成 Erlang,并且使用了许多 Phoenix Framework 开箱即用的工具。
🌐 Realtime is written in Elixir, which compiles to Erlang, and uses many tools the Phoenix Framework provides out of the box.

Elixir 与 Phoenix #
🌐 Elixir & Phoenix
凤凰很快,能处理百万级的并发连接。
🌐 Phoenix is fast and able to handle millions of concurrent connections.
Phoenix 能够处理许多并发连接,因为 Elixir 提供了轻量级进程(不是操作系统进程)来进行工作。
🌐 Phoenix can handle many concurrent connections because Elixir provides lightweight processes (not OS processes) to work with.
面向客户的 WebSocket 服务器需要处理大量并发连接。Elixir 和 Phoenix 可以让 Supabase Realtime 集群轻松做到这一点。
🌐 Client-facing WebSocket servers need to handle many concurrent connections. Elixir & Phoenix let the Supabase Realtime cluster do this easily.
通道 #
🌐 Channels
通道是使用 Phoenix Channels 实现的,它使用 Phoenix.PubSub 并带有默认的 Phoenix.PubSub.PG2 适配器。
🌐 Channels are implemented using Phoenix Channels which uses Phoenix.PubSub with the default Phoenix.PubSub.PG2 adapter.
PG2 适配器使用 Erlang 的进程组来实现 PubSub 模型,在这个模型中,发布者可以向多个订阅者发送消息。
🌐 The PG2 adapter uses Erlang process groups to implement the PubSub model where a publisher can send messages to many subscribers.
全球集群 #
🌐 Global cluster
Presence 是一个内存中的键值存储,由 CRDT 支持。当用户连接到集群时,该用户的状态会发送到所有已连接的 Realtime 节点。
🌐 Presence is an in-memory key-value store backed by a CRDT. When a user is connected to the cluster the state of that user is sent to all connected Realtime nodes.
广播让你可以从任何已连接的客户端向通道发送消息。连接到同一通道的其他客户端都会收到这条消息。
🌐 Broadcast lets you send a message from any connected client to a Channel. Any other client connected to that same Channel will receive that message.
这个功能在全球范围内都可用。一个连接到美国实时节点的客户端可以向另一个连接到新加坡节点的客户端发送消息。将两个客户端连接到同一个实时通道,他们都会收到相同的消息。
🌐 This works globally. A client connected to a Realtime node in the United States can send a message to another client connected to a node in Singapore. Connect two clients to the same Realtime Channel and they'll all receive the same messages.
广播对于快速将消息传递给同一地点的用户非常有用。如果一组客户端连接到新加坡的一个节点,消息只需要发送到新加坡的那个实时节点然后返回即可。如果用户靠近某个实时节点,他们会在向集群 ping 的时间内收到广播消息。
🌐 Broadcast is useful for getting messages to users in the same location rapidly. If a group of clients are connected to a node in Singapore, the message only needs to go to that Realtime node in Singapore and back down. If users are close to a Realtime node they'll get Broadcast messages in the time it takes to ping the cluster.
多亏了实时集群,你(一个了不起的 Supabase 用户)不用去考虑你的客户端连接的是哪个地区。
🌐 Thanks to the Realtime cluster, you (an amazing Supabase user) don't have to think about which regions your clients are connected to.
如果你在使用广播、在线状态或数据库变更流,消息总是会通过最短的路径到达你的用户。
🌐 If you're using Broadcast, Presence, or streaming database changes, messages will always get to your users via the shortest path possible.
正在连接数据库 #
🌐 Connecting to a database
Realtime 让你可以监听来自 Postgres 数据库的变更。当有新客户端连接到 Realtime 并初始化 postgres_changes Realtime 扩展时,集群会连接到你的 Postgres 数据库,并开始从复制槽中流式传输变更。
🌐 Realtime allows you to listen to changes from your Postgres database. When a new client connects to Realtime and initializes the postgres_changes Realtime Extension the cluster will connect to your Postgres database and start streaming changes from a replication slot.
Realtime 知道你的数据库所在的区域,并会从尽可能最近的区域连接它。
🌐 Realtime knows the region your database is in, and connects to it from the closest region possible.
每个实时区域至少有两个节点,所以如果一个节点离线,另一个节点应该会重新连接并再次开始流式传输更改。
🌐 Every Realtime region has at least two nodes so if one node goes offline the other node should reconnect and start streaming changes again.
来自 Postgres 的广播 #
🌐 Broadcast from Postgres
实时广播会在你的数据库发生变化时发送消息。在后台,实时广播会在 realtime.messages 表上创建一个发布。然后它会读取这个表的预写日志(WAL)文件,每当有插入操作发生时就发送一条消息。消息会以 JSON 包的形式通过 WebSocket 发送。
🌐 Realtime Broadcast sends messages when changes happen in your database. Behind the scenes, Realtime creates a publication on the realtime.messages table. It then reads the Write-Ahead Log (WAL) file for this table, and sends a message whenever an insert happens. Messages are sent as JSON packages over WebSockets.
realtime.messages 表按天分区。这允许通过删除旧分区来高效地删除旧消息。分区会保留 3 天后再删除。
🌐 The realtime.messages table is partitioned by day. This allows old messages to be deleted performantly, by dropping old partitions. Partitions are retained for 3 days before being deleted.
广播默认使用 实时授权 来保护你的数据。
🌐 Broadcast uses Realtime Authorization by default to protect your data.
流式传输预写日志 #
🌐 Streaming the Write-Ahead Log
当连接到你的数据库时,会获取一个 Postgres 逻辑复制槽。
🌐 A Postgres logical replication slot is acquired when connecting to your database.
实时通过轮询复制槽并将通道订阅 ID 添加到每个 WAL 记录来传递更改。
🌐 Realtime delivers changes by polling the replication slot and appending channel subscription IDs to each wal record.
订阅 ID 是表示集群中底层套接字的 Erlang 进程。这些 ID 在全球范围内是唯一的,发送给进程的消息会由 Erlang 虚拟机自动路由。
🌐 Subscription IDs are Erlang processes representing underlying sockets on the cluster. These IDs are globally unique and messages to processes are routed automatically by the Erlang virtual machine.
在收到带有订阅 ID 的投票查询结果后,实时会把记录发送给那些客户端。
🌐 After receiving results from the polling query, with subscription IDs appended, Realtime delivers records to those clients.