9

免责声明:我不是实时架构专家,我只想提出一些个人考虑并评估其他人的建议或指出。

假设我们想设计一个实时分析系统。遵循 Lambda 架构 Nathan Marz 的定义,为了提供数据,我们需要一个批处理层(即 Hadoop),不断地从所有数据的数据集中重新计算视图,以及一个所谓的速度层(即 Storm),它不断处理视图的一个子集(由批处理层最后一次完全重新计算后进入的事件产生)。您可以通过将两者的结果合并在一起来查询您的系统。

这个选择背后的理由对我来说非常有意义,它结合了软件工程和系统工程的观察。拥有一个不断增长的不可变时间戳事实的主数据集使系统能够在计算视图时适应人为错误(如果你犯了错误,你只需修复它并在批处理层重新计算它们)并使系统能够回答几乎任何将来会出现的查询。此外,这样的数据存储只需要支持随机读取和批量插入,而用于速度/实时部分的数据存储需要有效地支持随机读取和随机写入,从而增加了其复杂性。

我对此讨论的反对/触发是,在某些情况下,这种方法可能是一种矫枉过正。为了讨论,假设我们做了一些简化:

  • 假设在我们的分析系统中,我们可以预先定义小时系统需要能够提供的一组不可变的用例\查询,并且它们将来不会改变。
  • 假设我们有有限的资源(工程能力、基础设施等)来实现它。存储进入我们系统的整个基本事件集,而不是预先计算视图\聚合,可能太昂贵了。
  • 让我们假设我们成功地减少了人为错误的影响(...)。

该系统仍然需要可扩展并处理不断增长的流量和数据。鉴于这些观察,我想知道什么会阻止我们设计一个完全面向流的架构。我想象的是一种架构,其中事件(即页面视图)被推送到流中,可能是 RabbitMQ + Storm 或 Amazon Kinesis,并且此类流的消费者将通过随机写入/更新直接更新所需的视图NoSQL 数据库(即 MongoDB)。

乍一看,在我看来,这种架构可以水平扩展。Storm 可以集群化,也可以预先保留 Kinesis 预期的 QoS。更多的传入事件意味着更多的流消费者,并且由于它们是完全独立的,没有什么能阻止我们添加更多的。关于数据库,使用适当的策略对其进行分片可以让我们将越来越多的写入分配到越来越多的分片。为了避免读取受到影响,每个分片可以有一个或多个读取副本。在可靠性方面,Kinesis 承诺将您的消息可靠地存储长达 24 小时,并且正确使用确认机制的分布式 RabbitMQ(或您选择的任何队列系统)可能会满足相同的要求。

亚马逊关于 Kinesis 的文档故意(我相信)避免将您锁定在特定的架构解决方案中,但我的总体印象是,他们希望推动开发人员简化 Lambda 架构并实现类似于我的完全基于流的解决方案。暴露了。为了更符合 Lambda 架构要求,没有什么能阻止我们在消费者不断更新我们的视图的同时拥有一组消费者,这些消费者处理传入的事件并将它们作为原子不可变单元存储在不同的数据存储中将来用于生成新视图(例如通过 Hadoop)或重新计算错误数据。

你对这个推理有什么看法?我想知道纯基于流的架构在哪些场景下无法扩展,如果您有任何其他观察结果,Lambda 架构与基于流的架构的优缺点。

4

0 回答 0