摘要:和Apache Flink同样开始于2011年的Apache Storm,这个开创性的分布式流处理系统,在技术上仍然可行且得到积极维护,但在大多数应用中已被Apache Flink等更先进的替代方案所超越。Storm今天仍然在数百个生产部署中继续每日处理数十亿
和Apache Flink同样开始于2011年的Apache Storm,这个开创性的分布式流处理系统,在技术上仍然可行且得到积极维护,但在大多数应用中已被Apache Flink等更先进的替代方案所超越。Storm今天仍然在数百个生产部署中继续每日处理数十亿事件,然而,相比Flink的快速增长,Storm在流处理领域的市场份额日薄西山。
Apache Storm 最初由 Nathan Marz 在创业公司 BackType 中开发。目标是为大数据时代提供一种实时流处理框架,因为当时主流的 Hadoop 是批处理的,延迟高,不适合实时场景。Storm 提出了“拓扑(Topology)”的概念,将流处理表示为一个不断运行的数据处理图。2011年,Twitter 收购了 BackType,Storm 也被带入 Twitter,并开源。
在 Apache Storm 里面,流处理应用程序是由 拓扑(Topology) 构成的,拓扑里主要有两种核心组件:
Spout: Storm 的 数据源, 从外部系统获取数据(比如 Kafka、消息队列、数据库、API、日志文件等),然后把数据转化为 Storm 内部的 Tuple(元组) 并发射(emit)到拓扑中。可以是 可靠的(reliable):保证消息至少处理一次。也可以是 不可靠的(unreliable):发出去就不管是否处理成功Bolt:Storm 中的 数据处理单元。Bolt 从 Spout 或其他 Bolt 接收 Tuple,然后进行处理,处理后可以发射新的 Tuple 给下游 Bolt。常见用途包括:过滤(Filter)转换(Transform)聚合(Aggregation,例如统计、求和)连接(Join)写入存储(sink,例如存到数据库、Elasticsearch、HDFStorm 的拓扑像一张 数据流图,Spout 是数据的 入口,Bolt 是数据的 加工/传输节点。它们之间用 Stream(流) 连接。
比如一个实时日志分析系统:
KafkaSpout → ParseBolt → FilterBolt → CountBolt → DatabaseBoltStorm 的主从架构以 Nimbus(协调主节点) 和 Supervisor(工作节点管理) 为核心,数据处理通过一套层级结构进行组织:Worker 进程 → Executor(线程)→ Task(具体任务)。该系统最具代表性的技术成就是其基于 XOR(异或)算法的确认机制:它通过 64 位校验和来追踪 Tuple 的处理树,伪阳性率约为 1/2^64 —— 在生产规模下几乎为零。
这种轻量级的可靠性机制仅需为每个根 Tuple 维护约 20 字节的元数据,无论处理树多么复杂。这是一个极具工程美感的设计,后来也影响了其他流处理系统。每个 Spout 发出的 Tuple 都会被分配一个随机的 64 位 ID,Acker Bolt 会维护一个异或校验值,当整个 Tuple 处理树完成时,这个值会被异或抵消为 0。数学上的优雅在于:当所有 Tuple 成功处理后,异或操作会彼此抵消(例如:a XOR b XOR b = a),最终 Acker 的校验值回归为零。
source :https://www.researchgate.net/publication/369810421/figure/fig2/AS:11431281138152701@1680721099238/Apache-Storm-Architecture-28.png
Storm 的分布式协调完全依赖于 Apache ZooKeeper,所有集群状态要么存储在 ZooKeeper 中,要么存储在本地磁盘中。这种设计允许组件无状态、快速失败并能无缝重启,但也带来了扩展性瓶颈。Twitter 的生产经验表明,ZooKeeper 客户端的连接数存在上限,在超过 300 到 1200 个工作节点时,需要使用自定义心跳守护进程和数据库级别的硬件配置来实现扩展。
Storm 的流处理模型将计算组织为 有向无环图(DAG):Spout 生成无限的 Tuple 流,Bolt 执行转换操作。它提供了多种复杂的分区策略,包括:
Shuffle Grouping(随机分发),Fields Grouping(基于哈希的字段分区),All Grouping(广播式复制)。这种灵活性支持复杂的事件处理模式,但相比现代具备自动查询优化能力的系统,仍需要手动进行性能调优。
Storm 提供了多层级的并行控制,包括 Worker(进程级)、Executor(线程级)和 Task(组件实例级)。用户可以在每个层级上独立配置并行度,唯一的约束是 Executor 数量不能超过 Task 数量。该设计支持在无需重新部署拓扑的前提下进行 动态负载均衡,但也要求使用者具备较深入的分布式系统知识。
SQL接口流式数据处理的用户接口主要分为两类,一类以代码为主,例如Spark,Flink等,另一类提供以SQL或者类SQL为主要接口,例如ksqlDB,proton等。当然流行的引擎像Spark,Flink也会提供SQL接口,FlinkSQL,SparkSQL。
Squall提供了在Apache Storm之上的SQL接口,使用户能够使用熟悉的SQL语法来处理实时流数据,而不需要直接编写复杂的Storm拓扑代码。降低了实时数据分析的技术门槛。
Apache Storm 的创新在于把“实时流处理”变得像批处理一样可编程和可扩展;它的优点是低延迟、高吞吐、容错性强,为现代流处理框架奠定了基础。Storm 提出“像处理批数据一样简单地处理实时数据”,开创了通用流处理框架的先河。用 Spout + Bolt 的抽象方式,将数据流建模成一个 有向无环图 (DAG), 让开发者能像搭积木一样组合流处理逻辑。基于 XOR(异或)算法的确认机制,实现 “至少一次 (at-least-once)” 语义,保证消息不会丢失。
在当年Storm 被很多公司(Yahoo、Alibaba、Flipkart 等)用于实时推荐、日志分析、风控等系统。但是随着 Apache Spark 推出 Spark Streaming,以及更先进的 Apache Flink 面世,Storm 开始显得落后,包括:
早期版本不支持事件时间(Event Time)和窗口操作;缺乏完善的容错机制(消息至少处理一次);开发调试成本高,部署复杂;社区响应速度慢,创新速度减缓。“夜阑卧听风吹雨,铁马冰河入梦来。” 风暴过后,是一片寂静。
来源:闻数起舞