这是问题所在:
安装在许多不同服务器上的“代理”每 5 秒向中央服务器发送一次“心跳”信号。怎么主动发现错过心跳超过10秒的并发出警报?
如果您不考虑可扩展性,问题就很简单。以最简单的形式,您可以在数据库表中记录从每个代理接收到的最新心跳的时间戳,并运行常规查询以查找早于阈值的心跳。
然而,该解决方案无法扩展到数百万个代理。
我正在寻找使这成为可能的算法或技术。
这是问题所在:
安装在许多不同服务器上的“代理”每 5 秒向中央服务器发送一次“心跳”信号。怎么主动发现错过心跳超过10秒的并发出警报?
如果您不考虑可扩展性,问题就很简单。以最简单的形式,您可以在数据库表中记录从每个代理接收到的最新心跳的时间戳,并运行常规查询以查找早于阈值的心跳。
然而,该解决方案无法扩展到数百万个代理。
我正在寻找使这成为可能的算法或技术。
每次代理报告心跳时: 1. 在地图中找到它 2. 从相关集中删除它 3. 在地图中更新它 4. 将其添加到相关集中
定义一个线程:每秒一次,最旧的集合过期。它应该是空的。如果没有 - 它包含未报告的代理的 ID。一旦集合过期,您可以重复使用它(集合的循环数组)。
我相信它可以在没有锁的情况下实现(也许你需要 12 套)。
在不了解语言和平台的情况下,很难就详细实现向您提供建议,但我的建议与 Lior Kogan 的建议有些相似。但是,在我看来,您只需要两组并且不涉及地图:
假设您有两个变量代表集合,A 和 B。
每个心跳都会从集合 A 中删除代理 ID。每 5 秒,不同的线程会针对 B 中的每个代理 ID 发出警报,然后设置 B = A,最后但并非最不重要的一点是创建一个包含所有代理 ID 和集合 A 的集合等于那个(如果代理 id 的数量真的很大,你可以在一个检查和另一个检查之间准备新的集合,只在剩余的时间里休眠)。仅在更改指向每个集合的变量时才需要锁定,前提是您使用无锁集合集合。性能在很大程度上取决于所述实现的算法复杂性,如果你采用这种方式,你应该优先考虑性能最好的那个(不一定是最好的 big-O,例如,如果最坏情况下的延迟对你很重要)。
作为旁注,如果内存不是问题或故障相对较少,当您检查是否需要发出警报并这样做时,您可以在自己的线程上执行此操作并获得可能有趣的性能加速(再次,平台和运行时很重要,因为在 erlang 中这将是一件轻而易举的事,但在 Windows 中,如果故障很少,则创建一个完整的新线程的成本可能会超过性能收益),但代价是将旧的 B 设置在内存中。
MongoDB 非常适合这种类型的使用。虽然不完全是一种算法,但它确实符合创建此服务所需的基本技术的要求。我们在 CopperEgg 使用它来让我们的RevealCloud产品完全按照您所说的去做 - 我们会在系统消失一段时间后发送警报 - 每 5 秒采样一次。我很想听听更多关于您的想法和用例的信息。你能提供更多细节吗?