繁体   English   中英

您如何应对分布式系统中没有事件的情况?

[英]How do you react to the absence of an event in a distributed system?

我有一个收集 session 数据的系统。 session 由许多不同的事件组成,例如“会话开始”和“动作 X 执行”。 无法确定 session 何时结束,因此会定期发送心跳事件。

这是主要的并发症:无法确定 session 是否已结束,唯一的方法是尝试对没有事件做出反应,即不再有心跳。 如何在分布式系统中有效且正确地做到这一点?

这是问题的更多背景:

然后必须将事件组合成代表会话的对象。 session 对象稍后会使用来自其他系统的附加数据进行更新,最终它们用于计算会话数、平均 session 长度等。

系统必须水平扩展,因此有多个服务器接收事件,并有多个服务器处理它们。 属于同一 session 的事件可以发送到不同的服务器并由不同的服务器处理。 这意味着无法保证它们会按顺序处理,并且还有其他复杂性意味着事件可以重复(并且总是存在丢失某些事件的风险,无论是在它们到达我们的服务器之前,还是在处理时)。

其中大部分已经存在,但是对于如何有效和正确地确定 session 何时结束,我没有很好的解决方案。 我现在这样做的方式是定期搜索“不完整” session 对象的集合,以查找在等于两个心跳的时间内未更新的任何对象,然后将它们移动到具有“完整”会话的另一个集合中。 此操作耗时且效率低下,并且无法很好地横向扩展。 基本上,它包括在代表最后时间戳的列上对表进行排序,并过滤掉任何不够旧的行。 听起来很简单,但是很难并行化,如果你经常这样做,你将不会做任何其他事情,数据库将忙于过滤你的数据,如果你不经常这样做,每次运行都会很慢,因为有太多无法处理。

当 session 有一段时间没有更新时,我想做出反应,不要轮询每个 session 以查看它是否已更新。

更新:只是为了给你一种规模感; 任何时候都有数十万个会话处于活动状态,最终将有数百万个。

想到的一种可能性:

在跟踪会话的数据库表中,添加一个时间戳字段(如果您还没有),该字段记录 session 上次“活动”的时间。 每当您收到心跳时更新时间戳。

当您创建 session 时,安排一个“计时器事件”在适当的延迟后触发,以检查 session 是否应该过期。 当计时器事件触发时,检查会话的时间戳以查看在计时器等待的时间间隔内是否有更多活动。 如果是这样,则 session 仍处于活动状态,因此请安排另一个计时器事件稍后再检查。 如果不是,则 session 已超时,因此请将其删除。

如果使用这种方法,每个 session 将始终有一个服务器负责检查它是否过期,但不同的服务器可以负责不同的会话,因此工作量可以均匀分布。 当心跳进入时,哪个服务器处理它并不重要,因为它只是更新(可能)在所有服务器之间共享的数据库中的时间戳。

仍然涉及一些轮询,因为您将获得定期计时器事件,这些事件使您检查 session 是否已过期,即使它尚未过期。 如果您可以在每次心跳到达时取消挂起的计时器事件,则可以避免这种情况,但是对于多个服务器,这很棘手:处理心跳的服务器可能与安排计时器的服务器不同。 无论如何,所涉及的数据库查询是轻量级的:只需通过其主键查找一行(session 记录),没有排序或不等式比较。

所以你正在收集心跳; 我想知道您是否可以有一个批处理(或其他东西)来遍历收集的心跳,以寻找暗示 session 结束的模式。

准确度取决于心跳的规律性以及您扫描收集到的心跳的频率。

优点是您通过单一机制处理所有心跳(在一个地方 - 您不必自己轮询每个心跳)因此应该能够扩展 - 如果它是一个以数据库为中心的解决方案应该能够处理大量数据,对吧?

可能有一个更优雅的解决方案,但我的大脑刚刚有点充实:)

暂无
暂无

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

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