【发布时间】:2016-05-23 09:03:50
【问题描述】:
我在玩 elixir 和 phoenix 并尝试实现提醒功能,即 todo 与未来的日期时间,它应该在那个日期时间提醒你。
我想到了以下幼稚的解决方案:
1)使用简单的一对一策略,并为每个提醒创建一个进程,该进程将使用超时并在完成后死亡
2) 在单个进程中聚合所有提醒,将提醒存储在状态中,每隔几秒检查一次日期时间,并在警报后删除。
有人可以详细说明每种解决方案,并可能给出更明智的解决方案,谢谢
【问题讨论】:
我在玩 elixir 和 phoenix 并尝试实现提醒功能,即 todo 与未来的日期时间,它应该在那个日期时间提醒你。
我想到了以下幼稚的解决方案:
1)使用简单的一对一策略,并为每个提醒创建一个进程,该进程将使用超时并在完成后死亡
2) 在单个进程中聚合所有提醒,将提醒存储在状态中,每隔几秒检查一次日期时间,并在警报后删除。
有人可以详细说明每种解决方案,并可能给出更明智的解决方案,谢谢
【问题讨论】:
我建议考虑规模。 假设您有一台服务器来处理 x 个提醒:
在第一个解决方案中,我们有 x 个进程,每个进程都有自己的计时器,当计时器结束时,它将发送一条消息并终止。
在第二个解决方案中,我们将有一个进程,大概会找到所有相关的提醒并相应地处理它们
x 有多大?
如果 x 是数千个并且提醒是短暂的,那么也许我会说第一个解决方案更好,因为您有更好的容错设计,因为“提醒”被进程分开,但如果 x 大得多,那么它可能无法很好地扩展,您将有很多进程,每个进程都有一个计时器,不建议这样做。
我要补充一点,如果您有长时间运行的提醒,比如说从现在起一年的提醒,而不是您需要让一个进程运行一年直到它到期,这真的无法扩展。
当您处理大量提醒时,第二种解决方案的扩展性更好。 您将有一个可能每秒运行一次的计时器,它将汇总应该大约在那个时间运行的相关提醒并处理它们,长时间运行的提醒将不再是问题。
【讨论】:
我相信第一个选项要好得多,既简单又特别是可扩展性。 Erlang 旨在以高效的方式处理大量同时运行的轻量级进程。进程也可以分布在集群中的多台机器上,因此您基本上可以无限扩展。
启动一个简单地调用send_after/3 并以“通知调度程序”进程为目标的新进程非常简单,并且对性能的影响很低 - 如果出现问题并且该进程终止,您只会丢失一个提醒。所有其他人都被隔离了,仍然会开火。
通过将所有提醒存储在一个进程中,您将自己置于一个非常不舒服的位置,原因如下:
x秒遍历整个列表将是一项昂贵的操作; send_after/3 具有更高效的调度/调度机制,并且内置于...更少的工作,更少的复杂性;在大多数编程语言中,并发很难以安全的方式实现,因此人们像避免瘟疫一样避免它。在 Elixir 和 Erlang 中,情况正好相反——你想尽可能多地使用它,并且这样做会看到明显的收益。分而治之!
【讨论】: