简体   繁体   English

elixir凤凰提醒功能

[英]elixir phoenix reminder functionality

I am playing around with elixir and phoenix and tried to implement reminders functionality, ie todo with future datetime, which should alert you at that datetime. 我正在玩elixir和phoenix,并尝试实现提醒功能,即使用未来的日期时间,这应该在该日期时间提醒您。

I have the following naive solutions in mind: 我有以下天真的解决方案:

1) use simple one for one strategy and for each reminder create a process, which would use timeout and die after completion 1)使用简单的一对一策略,并为每个提醒创建一个进程,该进程将使用超时并在完成后死亡

2) aggregate all reminders in a single process, store reminders in state, check datetime every few seconds and remove after alerting. 2)在一个进程中聚合所有提醒,在状态中存储提醒,每隔几秒检查一次日期时间,并在发出警报后删除。

Could someone elaborate on each solution and may be give a more sensible one, thanks 有人可以详细说明每个解决方案,也许可以给出一个更明智的解决方案,谢谢

I suggest thinking about scale. 我建议考虑规模。 let's say you have one server that handles x reminders: 假设您有一台处理x提醒的服务器:

  1. In the first solution we have x processes, each with its own timer, when the timer ends it will send a message and die. 在第一个解决方案中,我们有x个进程,每个进程都有自己的计时器,当计时器结束时它会发送一条消息并死掉。

  2. In the second solution we'll have a single process that will presumably find all the relevant reminders and handle them accordingly 在第二个解决方案中,我们将有一个单一的流程,可能会找到所有相关的提醒并相应地处理它们

How big is x? x有多大?

If x is in the thousands and the reminders are short lived then maybe I would say solution number one is better because you have a better fault tolerant design as the 'reminders' are separated by processes, but if x is much bigger then it might not scale well, you would have a lot of processes each with a timer, it's not really recommended. 如果x是成千上万并且提醒是短暂的,那么也许我会说第一个解决方案更好,因为你有一个更好的容错设计,因为'提醒'被进程分开,但如果x大得多,那么它可能不会很好地扩展,你会有很多进程,每个进程都有一个计时器,这是不是真的推荐。

I would add that if you have long running reminders, let's say a reminder for a year from now, than you would need to have a process running for a year until it expires, this really doesn't scale. 我想补充一点,如果你有长时间运行的提醒,那么让我们说一年后的提醒,比你需要让一个进程运行一年直到它到期,这真的不能扩展。

The second solution scales better when you're dealing with a lot of reminders. 当您处理大量提醒时,第二种解决方案可以更好地扩展 You would have a timer that maybe runs every second, it will aggregate the relevant reminders that should run approximately at that time and handle them, long running reminders wouldn't be a problem anymore. 你可能有一个可能每秒运行一次的计时器,它会汇总大约应该在那时运行并处理它们的相关提醒,长时间运行的提醒不再是问题。

I believe the first option is much, much better, both for simplicity and especially for scalability. 我相信第一个选项要好得多,既简单又特别是可扩展性。 Erlang was designed to handle a high number of lightweight processes running concurrently in an efficient manner. Erlang旨在以高效的方式处理大量并发运行的轻量级进程。 Processes can also be distributed across many machines in a cluster, so you can essentially scale to infinity. 进程也可以分布在群集中的许多计算机上,因此您可以实际扩展到无穷大。

Starting a new process that simply calls send_after/3 with a "notification dispatcher" process as the target is extremely simple and has a low performance impact - and if something goes wrong and that process dies, you only lose one reminder. 启动一个简单调用send_after/3并使用“通知调度程序”进程作为目标的新进程非常简单且性能影响很小 - 如果出现问题并且该进程终止,则只会丢失一个提醒。 All others are isolated and will still fire. 所有其他人都是孤立的,仍然会被解雇。

By storing all your reminders in a single process, you're putting yourself in a very uncomfortable position for several reasons: 通过将所有提醒存储在一个过程中,您将自己置于一个非常不舒服的位置,原因如下:

  • If the process dies, all of your reminders are gone. 如果进程终止,则所有提醒都将消失。 This is probably unacceptable, so you'd need to come up with a way of persisting them to disk so you could recover from a crash... more work, more complexity; 这可能是不可接受的,所以你需要想出一种方法来将它们保存到磁盘上,这样你就可以从崩溃中恢复过来......更多的工作,更多的复杂性;
  • If the number of reminders grows too high, traversing the entire list every x seconds will be an expensive operation; 如果提醒的数量增长得太高,则每隔x秒遍历整个列表将是一项昂贵的操作; send_after/3 has a much more efficient scheduling/dispatching mechanism and it's built right in... less work, less complexity; send_after/3具有更高效的调度/调度机制,并且内置于......工作量少,复杂度低;
  • If everything is in a single megaprocess, you can't distribute the load across nodes in your cluster, so you're bound by the computing power of the machine running that megaprocess. 如果所有内容都在一个大型进程中,则无法在群集中的节点之间分配负载,因此您必须受运行该大型进程的计算机的计算能力的限制。

In most programming languages, concurrency is extremely hard to do in a safe way, so people avoid it like the plague. 在大多数编程语言中,并发性很难以安全的方式进行,因此人们就像瘟疫一样避免它。 In Elixir and Erlang, it's the exact opposite - you want to use it as much as possible, and you see noticeable gains by doing so. 在Elixir和Erlang中,它恰恰相反 - 你想尽可能多地使用它,你会看到明显的收益。 Divide and conquer! 分而治之!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM