您如何对分布式系统中缺少事件做出反应?

时间:2011-04-28 06:31:12

标签: events architecture distributed

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

这是主要的复杂因素:没有办法确定会话是否已经结束,唯一的方法是尝试对事件的缺席做出反应,即不再有心跳。如何在分布式系统中高效准确地完成此任务?

以下是该问题的更多背景知识:

然后必须将事件组合到表示会话的对象中。会话对象稍后使用来自其他系统的其他数据进行更新,最终用于计算会话数,平均会话长度等内容。

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

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

我想对会话暂时没有更新时做出反应,而不是轮询每个会话以查看它是否已更新。

更新:只是为了给你一种规模感;随时有数十万个会话活动,最终会有数百万个。

2 个答案:

答案 0 :(得分:2)

浮现在脑海中的一种可能性:

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

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

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

还有一些轮询,因为你会得到定期的计时器事件,这些事件会让你检查会话是否已过期,即使它已经过期。如果您可以在每次心跳到达时取消挂起的计时器事件,但是使用多个服务器非常棘手,则可以避免这种情况:处理心跳的服务器可能与计划的计时器不同。无论如何,涉及的数据库查询是轻量级的:只需按主键查找一行(会话记录),不进行排序或不等式比较。

答案 1 :(得分:0)

所以你要收集心跳;我想知道你是否可能有一个批处理过程(或其他东西)在收集的心跳上运行,寻找暗示会话结束的模式。

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

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

可能会有一个更优雅的解决方案,但我刚才的脑子有点饱了:)