socket.io vs RethinkDB changefeed
Posted
技术标签:
【中文标题】socket.io vs RethinkDB changefeed【英文标题】: 【发布时间】:2015-08-12 05:01:08 【问题描述】:目前我正在使用没有 RethinkDB 的 socket.io,如下所示:
客户端向 socket.io 发出事件,socket.io 接收事件,向其他各种客户端发出,并保存到数据库中以保持持久性。连接的新客户端将从数据库中获取现有数据,然后通过 socket.io 监听新事件。
切换到 RethinkDB 和 changefeed 对我有什么帮助?
我看到与 RethinkDB 相同的工作方式是客户端可以执行 POST(插入到 RethinkDB)而不是发送到 socket.io,然后 socket.io 正在监视 RethinkDB 更改馈送并在它发送到所有客户端时接收新数据。
这种使用 RethinkDB 和 changefeed 的方法比我目前的方法更好吗?对我来说,他们都觉得他们完成了同样的事情,但我没有看到 RethinkDB 方法有任何明显的优势,而且因为我会去数据库而不是立即从服务器上的 socket.io 发出它会肯定会慢一点。
【问题讨论】:
【参考方案1】:首先,让我们澄清一下 socket.io 和 RethinkDB changefeeds 之间的关系。 Socket.io 旨在用于客户端(浏览器)和服务器(Node.js)之间的实时通信。 RethinkDB changfeeds 是您的服务器(Node.js)监听数据库更改的方式。客户端无法直接与 RethinkDB 通信。
实时应用程序的一个非常典型的架构是让 RethinkDB 更改源订阅数据库中的更改,然后使用 socket.io 将这些更改传递给客户端。客户端通常还会发出可以写入数据库的消息,具体取决于您的应用程序逻辑。
是的,您可以通过 socket.io 发出所有消息,然后将所有消息传递给所有客户端,然后将这些消息写入数据库以保持持久性。这确实更快,但这种方法有许多缺点。
1.数据库作为单一事实来源
最容易发现的问题如下:
如果您的应用无法向 数据库? 如果您尝试插入数据库的数据无效或重复,会发生什么情况?您是否编写应用程序逻辑来处理此问题? 如果 Node.js 服务器在发出 写查询?这些只是一些简单的示例,在这些示例中,由于您的架构,您将丢失或拥有不同步的数据。重申一下,您将丢失数据,因为您的主要事实来源是内存中。您的 Node.js 应用程序和数据库中的数据也可能存在差异。
关键是数据库应该始终是您的唯一真实来源,并且您应该只在数据写入磁盘时确认数据。我不确定其他人怎么能在晚上睡觉。
2。高级查询
如果您只是通过 socket.io 将来自所有客户端的所有新消息传递给所有客户端,那么您现在必须在客户端中有一些非常复杂的逻辑,以便过滤掉所有真正重要的数据。考虑到您正在通过网络传递大量客户端实际上不会使用的无用数据。
另一种方法是编写一个发布/订阅系统,您可以在其中订阅某些频道(或类似的频道),以便过滤掉对客户端真正重要的数据。
RethinkDB 通过提供它自己的查询语言来解决这个问题,您可以将其附加到 changefeeds。例如,如果客户需要我的users
表中年龄在 20 到 30 岁之间、居住在加利福尼亚州、距离旧金山 10 英里并且在过去 6 个月内买过书的所有用户,这可以用 ReQL(RethinkDB 的查询语言)表示,并且可以为该查询设置一个 changefeed,以便客户端仅在 relevant 更改时收到通知。仅使用 Socket.io 和 Node.js 就很难做到这一点。
3.可扩展性
RethinkDB 解决的最后一个问题是,它是一种更具可扩展性的解决方案,只需将所有内容都存储在内存中(通过 Socket.io 和 Node.js)。因为 RethinkDB 是从一开始就构建为分布式的,所以您可以拥有一个由 20 多个 RethinkDB 节点组成的集群,其中包含分片和副本。您编写的每个 RethinkDB 查询都是默认分发的。现在,您可以拥有 20 多个其他 Node.js 节点,它们都是无状态的并且都在监听 changfeed。因为数据库是事实的中心来源,所以这不是问题。
另一种方法是将自己限制在一台服务器上,拥有一些其他发布/订阅系统(例如,基于 Reddis 之类的东西构建),只有一个可供轮询的数据库......可能还有更多示例,但你可以看到我要去哪里。
我很想知道这是否回答了您的问题,以及我是否了解您的来历。一开始很难了解如何构建应用程序,但对于大多数实时架构来说,它确实是一个优雅的解决方案。
【讨论】:
非常有帮助 :) 对于高级查询,请考虑使用多房间聊天应用程序,将消息发送给房间中的客户。我不能只听 1 个 changefeed(所有聊天)并只向那个房间里的客户发送吗?r.table('chat').changes().run(r.conn, function(err, cursor) cursor.each(function(err, row) io.to('room-' + row.new_val.id, row.new_val); // 1 room ); );
... 所以高级查询与这个特定的用例无关,因为它们会涉及到每个房间看一个 changefeed,这是相当浪费的。为此,我们也不需要“在 [the] 客户端中具有相当复杂的逻辑”。
“所以高级查询与这个特定的用例无关,因为它们会涉及到每个房间查看一个 changefeed,这是相当浪费的。”变更提要实际上很便宜,因此最好设置更具体的不同变更提要,而不是设置一个您的应用程序逻辑必须稍后处理的变更提要。
“我不能只收听 1 个 changefeed(所有聊天)并只发送给那个房间里的客户吗?”是的,你也可以这样做。如果您只想要大量聊天消息,那很好。话虽如此,我会在您需要时立即切换到编写 ReQL 查询 + 变更源,而不是将其添加到应用程序层。同样,changefeeds 查询非常便宜,不必担心是否慷慨地开放它们。
很高兴知道(changefeed 很便宜),但应用程序逻辑只是io.to('room-' + row.new_val.id, row.new_val);
,所以一点也不困难。
这个答案澄清了我的很多疑惑,即使我将在 golang 中使用 websockets。以上是关于socket.io vs RethinkDB changefeed的主要内容,如果未能解决你的问题,请参考以下文章
Node.Js + Socket.IO vs SignalR vs C# WebSocket 服务器