【问题标题】:Persistent messages over channels渠道上的持久消息
【发布时间】:2016-05-14 18:16:04
【问题描述】:

我正在使用 phoenix 框架构建一个应用程序,该应用程序将使用数千个通道,用户将每秒钟发送一次长的、经纬度信息的消息。

所以,我每秒会收到数千条消息。

问题是,我将如何将收到的每条消息存储到数据库中? 请耐心描述一下我对此的想法,因为我正在考虑以下选项来处理将消息存储到 DB 中:

  1. 使用相同的连接过程将消息存储到数据库中。

    可能的警告: 这会影响通道的延迟时间和性能吗?

  2. 为每个通道创建一个数据库专用进程来存储其消息。

    可能的警告: 那么,如果我有 100'000 个通道,我将需要另外 100'000 个进程来存储消息,这样可以吗?考虑到 erlang 进程既精简又便宜?

  3. 为所有通道创建一个数据库进程,然后来自任何通道的每条消息都将排队,然后由这个单独的数据库进程存储。

    可能的警告: 一个进程存储上千通道的所有消息,消息队列会走高,会慢吗?

那么,存储每秒来自数千个频道的消息的推荐方法是什么?

编辑

我将使用dynamo db,它可以轻松处理数千个并发请求。

【问题讨论】:

  • 首先,Phoenix 默认为您提供数据库进程池。其次,每个用户已经有一个进程,所以延迟不应该受到影响。

标签: erlang elixir phoenix-framework


【解决方案1】:

最重要的问题是连接通道中的请求是否可以在写入数据库之前完成。您需要考虑如果连接过程响应客户端并且数据库发生某些事情以使其被写入会发生什么。如果数据丢失是可以接受的,那么数据库访问可以异步完成,如果不是,那么它需要同步,例如只有在数据库确认已存储请求后才响应客户端。

如果数据可以异步存储到数据库中,那么最好生成一个新进程来完成它或将其添加到队列中(2 和 3)。如果必须同步存储数据,那么在同一进程中处理它会更容易 (1)。请注意,请求必须在进程之间复制,如果数据库写入在不同的进程中处理并且消息很大,则可能会影响性能。

可以提高异步写入的可靠性,例如通过在将请求写入数据库之前将请求持久存储在某处,然后回复客户端,然后尝试完成数据库写入,然后可以在以下情况下重试数据库已关闭。但这有点复杂。

您还需要确定瓶颈,即架构中最慢的部分。如果是数据库,那么无论您是创建一个对数据库的请求队列还是为每个连接创建一个新进程,这些请求都将堆积在该单个进程的内存中或创建的进程数量中.

我可能会在不牺牲太多延迟的情况下确定数据库可以处理多少并行连接,并创建一个进程池来处理请求。然后我会创建一个队列来将请求分派给那些池化进程。为了处理更大的消息,我将从队列中获取一个令牌(写入权限)并直接连接到数据库以避免过多地复制消息。如果稍后发现任何瓶颈,该架构将更容易扩展,例如持久存储传入的消息,然后才能将它们写入数据库或在数据库过载时平衡对其他节点的请求。

【讨论】:

  • 您仍然需要回答最重要的问题,您应该在数据库写入后才回复客户端,或者您可以立即回复并稍后写入,冒着数据不会的风险因网络或其他问题写到最后。
  • 用户不应该等待数据库写入消息,但是,写入所有消息很重要..
  • 你回答了你自己的问题。不要在同一进程中访问数据库,将其发送到另一个进程,该进程将消息持久地写入本地计算机的某个位置,然后回复用户。然后另一个进程将尝试将消息写入数据库。如果写入成功,请从本地计算机上的持久存储中删除消息。如果这听起来很麻烦,那么事实就是如此,您可能希望为了简单而牺牲延迟并同步处理所有事情。
  • 谢谢,好的,我想我会先将消息写入本地数据库,并有一个过程将消息从本地数据库传输到远程数据库,最终存储消息,我会做测试看看进展如何..
猜你喜欢
  • 2015-12-29
  • 2020-10-02
  • 1970-01-01
  • 2012-12-26
  • 1970-01-01
  • 2014-02-05
  • 2016-12-30
  • 2023-04-05
  • 2023-03-20
相关资源
最近更新 更多