当前位置: 首页 > 软件库 > 数据库相关 > >

realtime

授权协议 Apache-2.0 License
开发语言 C/C++
所属分类 数据库相关
软件类型 开源软件
地区 不详
投 递 者 蔡鹏程
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Supabase Realtime

Listens to changes in a PostgreSQL Database and broadcasts them over websockets.
Report Bug · Request Feature

Hiring

Supabase is hiring Elixir experts to work full-time on this repo. If you have the experience, apply online.

Project Status

  • Alpha: Under heavy development
  • Public Alpha: Ready for use. But go easy on us, there may be a few kinks.
  • Public Beta: Stable enough for most non-enterprise use-cases
  • Public: Production-ready

This repo is still under heavy development and the documentation is constantly evolving. You're welcome to try it, but expect some breaking changes. Watch "releases" of this repo to get notified of major updates. And give us a star if you like it!

Introduction

What is this?

This is a server built with Elixir using the Phoenix Framework that allows you to listen to changes in your PostgreSQL database via logical replication and then broadcast those changes via websockets.

Realtime server works by:

  1. listening to PostgreSQL's replication functionality (using PostgreSQL's logical decoding)
  2. converting the byte stream into JSON
  3. broadcasting over websockets

Why not just use PostgreSQL's NOTIFY?

A few reasons:

  1. You don't have to set up triggers on every table.
  2. NOTIFY has a payload limit of 8000 bytes and will fail for anything larger. The usual solution is to send an ID and then fetch the record, but that's heavy on the database.
  3. Realtime server consumes two connections to the database, then you can connect many clients to this server. Easier on your database, and to scale up you just add additional Realtime servers.

What are the benefits?

  1. The beauty of listening to the replication functionality is that you can make changes to your database from anywhere - your API, directly in the DB, via a console, etc. - and you will still receive the changes via websockets.
  2. Decoupling. For example, if you want to send a new slack message every time someone makes a new purchase you might build that functionality directly into your API. This allows you to decouple your async functionality from your API.
  3. This is built with Phoenix, an extremely scalable Elixir framework.

Does this server guarentee delivery of every data change?

Not yet! Due to the following limitations:

  1. Postgres database runs out of disk space due to Write-Ahead Logging (WAL) buildup, which can crash the database and prevent Realtime server from streaming replication and broadcasting changes.
  2. Realtime server can crash due to a larger replication lag than available memory, forcing the creation of a new replication slot and resetting streaming replication to read from the latest WAL data.
  3. When Realtime server falls too far behind for any reason, for example disconnecting from database as WAL continues to build up, then database can delete WAL segments the server still needs to read from, for example after reconnecting.

Quick start

We have set up some simple examples that show how to use this server:

Client libraries

Event Filters with Examples

Prerequisites for running event filter examples

import { RealtimeClient } = '@supabase/realtime-js'

var socket = new RealtimeClient(process.env.REALTIME_URL || 'ws://localhost:4000/socket')
socket.connect()

Supported event types

  • *
  • INSERT
  • UPDATE
  • DELETE

Supported event filters

  • Listen to all database changes
    • Channel format: realtime:*
// Listen to all deletes in database
var allChanges = socket
  .channel('realtime:*')
  .join()
  .on('DELETE', payload => { console.log('Delete received!', payload) })
  • Listen to a specific schema's changes
    • Channel format: realtime:schema
// Listen to all inserts from the 'public' schema
var allPublicInsertChanges = socket
  .channel('realtime:public')
  .join()
  .on('INSERT', payload => { console.log('Insert received!', payload) })
  • Listen to a specific table's changes
    • Channel format: realtime:schema:table
// Listen to all updates on the 'users' table in the 'public' schema
var allUsersUpdateChanges = socket
  .channel('realtime:public:users')
  .join()
  .on('UPDATE', payload => { console.log('Update received!', payload) })
  • Listen to a specific column's value changes
    • Channel format: realtime:schema:table:column=eq.value
// Listen to all changes to user ID 99
var allUserId99Changes = socket
  .channel('realtime:public:users:id=eq.99')
  .join()
  .on('*', payload => { console.log('Change received!', payload) })

Server

Database set up

The following are requirements for your database:

  1. It must be Postgres 10+ as it uses logical replication
  2. Set up your DB for replication
    1. It must have the wal_level set to logical. You can check this by running SHOW wal_level;. To set the wal_level, you can call ALTER SYSTEM SET wal_level = logical;
    2. You must set max_replication_slots to at least 1: ALTER SYSTEM SET max_replication_slots = 5;
  3. Create a PUBLICATION for this server to listen to: CREATE PUBLICATION supabase_realtime FOR ALL TABLES;
  4. [OPTIONAL] If you want to receive the old record (previous values) on UPDATE and DELETE, you can set the REPLICA IDENTITY to FULL like this: ALTER TABLE your_table REPLICA IDENTITY FULL;. This has to be set for each table unfortunately.

Server set up

The easiest way to get started is just to use our docker image. We will add more deployment methods soon.

# Update the environment variables to point to your own database
docker run                                  \
  -e DB_HOST='docker.for.mac.host.internal' \
  -e DB_NAME='postgres'                     \
  -e DB_USER='postgres'                     \
  -e DB_PASSWORD='postgres'                 \
  -e DB_PORT=5432                           \
  -e PORT=4000                              \
  -e JWT_SECRET='SOMETHING_SUPER_SECRET'    \
  -p 4000:4000                              \
  supabase/realtime

ALL OPTIONS

DB_HOST                 # {string}      Database host URL
DB_NAME                 # {string}      Postgres database name
DB_USER                 # {string}      Database user
DB_PASSWORD             # {string}      Database password
DB_PORT                 # {number}      Database port
DB_IP_VERSION           # {string}      (options: 'IPv4'/'IPv6') Connect to database via either IPv4 or IPv6. Disregarded if database host is an IP address (e.g. '127.0.0.1') and recommended if database host is a name (e.g. 'db.abcd.supabase.co') to prevent potential non-existent domain (NXDOMAIN) errors.
SLOT_NAME               # {string}      A unique name for Postgres to track where this server has "listened until". If the server dies, it can pick up from the last position. This should be lowercase.
PORT                    # {number}      Port which you can connect your client/listeners
SECURE_CHANNELS         # {string}      (options: 'true'/'false') Enable/Disable channels authorization via JWT verification.
JWT_SECRET              # {string}      HS algorithm octet key (e.g. "95x0oR8jq9unl9pOIx"). Only required if SECURE_CHANNELS is set to true.
JWT_CLAIM_VALIDATORS    # {string}      Expected claim key/value pairs compared to JWT claims via equality checks in order to validate JWT. e.g. '{"iss": "Issuer", "nbf": 1610078130}'. This is optional but encouraged.
MAX_REPLICATION_LAG_MB  # {number}      If set, when the replication lag exceeds MAX_REPLICATION_LAG_MB (value must be a positive integer in megabytes), then replication slot is dropped, Realtime is restarted, and a new slot is created. Warning: setting MAX_REPLICATION_SLOT_MB could cause database changes to be lost when the replication slot is dropped.

EXAMPLE: RUNNING SERVER WITH ALL OPTIONS

# Update the environment variables to point to your own database
docker run                                                       \
  -e DB_HOST='docker.for.mac.host.internal'                      \
  -e DB_NAME='postgres'                                          \
  -e DB_USER='postgres'                                          \
  -e DB_PASSWORD='postgres'                                      \
  -e DB_PORT=5432                                                \
  -e DB_IP_VERSION='IPv4'                                        \
  -e SLOT_NAME='supabase_realtime'                               \
  -e PORT=4000                                                   \
  -e SECURE_CHANNELS='true'                                      \
  -e JWT_SECRET='SOMETHING_SUPER_SECRET'                         \
  -e JWT_CLAIM_VALIDATORS='{"iss": "Issuer", "nbf": 1610078130}' \
  -e MAX_REPLICATION_LAG_MB=1000                                 \
  -p 4000:4000                                                   \
  supabase/realtime

Websocket Connection Authorization

Websocket connections are authorized via symmetric JWT verification. Only supports JWTs signed with the following algorithms:

  • HS256
  • HS384
  • HS512

Verify JWT claims by setting JWT_CLAIM_VALIDATORS:

e.g. {'iss': 'Issuer', 'nbf': 1610078130}

Then JWT's "iss" value must equal "Issuer" and "nbf" value must equal 1610078130.

NOTE: JWT expiration is checked automatically.

Development: Channels are not secure by default. Set SECURE_CHANNELS to true to test JWT verification locally.

Production: Channels are secure by default and you must set JWT_SECRET. Set SECURE_CHANNELS to false to proceed without checking authorization.

Authorizing Client Connection: You can pass in the JWT by following the instructions under Usage in the @supabase/realtime-js client library or as query param in the WebSocket URL (e.g. wss://abc.supabase.co/realtime/v1/websocket?vsn=1.0.0&apikey=jwt).

License

This repo is licensed under Apache 2.0.

Credits

Sponsors

We are building the features of Firebase using enterprise-grade, open source products. We support existing communities wherever possible, and if the products don’t exist we build them and open source them ourselves.

New Sponsor

 相关资料
  • 问题内容: 题 我有以下Firebase实时数据库: 在我的Android应用中,我这样查询 产生警告: 使用未指定的索引。考虑将“ .indexOn”添加到安全性和Firebase数据库规则中以获得更好的性能 如何正确索引?当数据增长时,我担心我的应用程序对未索引数据的查询将变得非常慢。 背景 我已经在我的规则文件中尝试过索引值: 但这仅在数据是标量但它们是键值对()的情况下才有效。 我不能像这

  • 问题内容: 通过控制面板向Firebase实时数据库添加新值时,我想在特定字段中保存当前日期/时间。 我该如何实现? 问题答案: 最佳做法是TIMESTAMP像这样保存数据。 还要记住,将设置为时,将其设置为,但是将其获取时,则将其设置为Long。为了获取数据,我建议您使用以下方法: 编辑:模型类应如下所示: 请记住,只是一个令牌,当它在写入操作期间用作子值时,它将转换为服务器端的数字。该日期仅在

  • 问题内容: 当我在ES中为文档建立索引时,我试图在刷新间隔内访问同一文档,并且搜索未返回结果。是否有Realtime GET支持,无论索引的“刷新率”如何,该支持都可以使文档一旦建立索引。我尝试将refresh_interval减小为500ms,而不是1s,但是我的搜索查询甚至在500ms之前就发生了,进一步减小它不是一个好主意。 问题答案: 为文档建立索引后,您可以立即获取它,而无需等待刷新间隔

  • 问题内容: 通过控制面板将新值添加到Firebase实时数据库时,我想在特定字段中保存当前日期/时间。 我该如何实现? 请帮我。 问题答案: 最好的做法是将您的数据保存为一个TIMESTAMP像这样ServerValue.TIMESTAMP。 还要记住,将设置为时,将其TIMESTAMP设置为Map,但是将其检索时,则将其设置为Long。为了获取数据,我建议您使用以下方法: 编辑:模型类应如下所示

  • 我已经创建了一个标准前台服务,并试图实现setValue它不会导致任何错误,但实时数据库没有更新,尽管祝酒词“耶”打印,这意味着OnCreative方法中没有问题,所以问题一定是数据库的实现参考,我的最终目标是使用实时位置纬度经度,所以如果有任何相关的东西,这将有助于我在RTD中设置值将是非常有帮助的,谢谢

  • 我的Firebase RealtimeDatabase包含一个名为Records在该表中有FirebaseUser Uid,在每个Uid中有日期,在每个日期中有一个产品列表。这是一个来自firebase控制台的示例。 在一个名为DailyTableActivity的活动中,有一个提示到DatePickerDialog的按钮和一个ListView元素,该元素应该为连接的用户显示对话框中特定日期(或当

  • 我正在将flutter应用程序从Firebase实时数据库迁移到Firestore。我在聊天应用程序中更新这段代码时遇到麻烦,因为firestore没有FireBaseAnimatedList。 旧代码: 现在只有错误是在动画中。我有错误:

  • 我是新手。我有一个非常基本的问题,但我试图在谷歌上找到它,但不明白。我的问题是。 在firebase中,谷歌表示: 任何人都可以在这种类型的安全规则中中断,即使是不使用你的应用程序的人。我得到了它。现在,如果我想制作聊天应用或小型社交应用,那么我应该使用什么样的安全规则? 这条规则足以让我的应用程序安全吗?我在下面发帖: 我的应用程序目标是在使用我的应用程序之前通过Firebase身份验证对用户进