2015-05-29 44 views
15

目前我使用socket.io没有RethinkDB这样的:socket.io VS RethinkDB changefeed

客户发出事件socket.io,接收事件,发出各种其他客户端,并保存到数据库为了持久。新的客户端连接将从数据库获取现有数据,然后通过socket.io监听新事件。

如何切换到RethinkDB和更换饲料在这里帮助我?

我看到与RethinkDB一样的工作方式是客户端可以执行POST(插入到RethinkDB中)而不是发送到socket.io,然后socket.io正在观看RethinkDB换件并向所有客户端发送时它接收新的数据。

这种方法如何使用RethinkDB和更换饲料比我目前的方法更好?对我来说,他们都觉得他们完成了同样的事情,但我在RethinkDB方法中看不到任何明显的优势,并且因为我会去db而不是直接从服务器上的socket.io发出它,它会肯定会慢一点。

回答

34

首先,让我们来澄清socket.io和RethinkDB换刀之间的关系。 Socket.io用于客户端(浏览器)和服务器(Node.js)之间的实时通信。 RethinkDB更新是服务器(Node.js)监听数据库更改的方式。客户端无法直接与RethinkDB通信。

实时应用程序的一个非常典型的架构是让RethinkDB更改订阅订阅数据库中的更改,然后使用socket.io将这些更改传递给客户端。客户端通常也会发送可写入数据库的消息,具体取决于您的应用程序逻辑。

是的,您可以通过socket.io发送所有消息,然后将所有消息传递给所有客户端,然后将这些消息写入数据库以实现持久性。这也是事实,这是更快的,但这种方法有许多缺点。

1.数据库真理

被发现的最简单的问题,单一来源如下:

  • 如果您的应用程序不能写东西到 数据库会发生什么?
  • 如果试图插入数据库的数据无效或重复,会发生什么情况?你编写应用程序逻辑来处理这个问题吗?
  • 如果Node.js服务器在发出 写查询之前发生故障,会发生什么情况?

这些只是一些简单的例子,在这些例子中,由于您的体系结构,您将丢失或失去同步数据。只是为了重申这一点,你将失去数据,因为你的真相的主要来源是内存。您的Node.js应用程序中的数据与您的数据库之间也可能有差异。

问题是,数据库应该始终是您的唯一真理来源,并且您应该只在数据写入磁盘时才确认数据。我不确定每晚有人能否在晚上睡觉。

2。高级查询

如果您只是通过socket.io将所有客户端的所有新消息传递给所有客户端,那么您现在必须在客户端中拥有一些非常复杂的逻辑,以便过滤出所有实际上非常重要的数据。考虑到你通过网络传递大量无用的数据,客户端实际上不会使用它们。

另一种方法是编写一个订阅某些渠道(或类似的东西)的发布/订阅系统,以过滤出对客户来说非常重要的数据。

RethinkDB通过提供它自己的查询语言来解决此问题,您可以附加到更改供稿。例如,如果客户需要我的users表中年龄在20至30岁之间的所有用户,他们居住在加利福尼亚州,距旧金山10英里,并且在过去6个月内购买过书籍,可以使用ReQL(RethinkDB的查询语言)表示,并且可以为该查询设置更换进料,以便仅当相关的更改时才会通知客户端。这对于Socket.io和Node.js来说很难做到。

3.扩展

即RethinkDB解决的是,它是一个更灵活的解决方案,只是在内存中存储的一切最后一个问题(通过Socket.io和Node.js的)。由于RethinkDB是从头开始构建的,因此您可以拥有包含分片和副本的20多个RethinkDB节点的集群。您编写的每个RethinkDB查询都是默认分发的。现在,您可以拥有20多个无状态的Node.js节点,并且都在监听更新。因为数据库是真相的中心来源,所以这不是问题。

另一种方法是将自己限制在一台服务器上,拥有一些其他的pub/sub系统(例如建立在像Reddis之类的东西上),只有一个数据库可以轮询......可能有更多的例子,但你可以看到我要去哪里。


我很想听听,如果这回答了你的问题,如果我得到你的出发到来。开始时如何构建应用程序有点困难,但它对于大多数实时体系结构来说确实是一个优雅的解决方案。

+1

非常有帮助:) 对于高级查询,请考虑多房间聊天应用程序,并将消息发送给房间中的客户。我不能只聆听1份换货(所有聊天)并只发送给那个房间的客户吗? ('room')()函数()函数(函数(err,row)){r.table('chat')。 + row.new_val.id,row.new_val); // 1 room }); });' ...所以高级查询与此特定用例无关,因为它们将涉及观察一个每个房间更换饲料,这是相当浪费的。我们也不需要在这个客户端有'非常复杂的逻辑'。 – user3096484

+0

“,所以高级查询与此特定用例无关,因为它们涉及每个房间观看一次换货,这相当浪费。”换刀实际上很便宜,所以最好设置更具体的不同换刀,而不是设置一个换刀,以便以后处理应用逻辑。 –

+2

“我不能只聆听1次换货(所有聊天)并只发送给那个房间的客户吗?”是的,你也可以这样做。如果你只想要一个聊天消息的话,那很好。话虽如此,我会在需要时立即转而编写ReQL查询+更换,而不是将其添加到应用程序层。同样,更换进度查询相当便宜,不用担心要慷慨地开放它们。 –