codecamp

Storm 基础知识

基础知识

Storm 是一个分布式的,可靠的,容错的数据流处理系统。它会把工作任务委托给不同类型的组件,每个组件负责处理一项简单特定的任务。Storm 集群的输入流由一个被称作 spout 的组件管理,spout 把数据传递给 bolt, bolt 要么把数据保存到某种存储器,要么把数据传递给其它的 bolt。你可以想象一下,一个 Storm 集群就是在一连串的 bolt 之间转换 spout 传过来的数据。

这里用一个简单的例子来说明这个概念。昨晚我在新闻节目里看到主持人在谈论政治人物和他们对于各种政治话题的立场。他们一直重复着不同的名字,而我开始考虑这些名字是否被提到了相同的次数,以及不同次数之间的偏差。

想像播音员读的字幕作为你的数据输入流。你可以用一个 spout 读取一个文件(或者 socket,通过 HTTP,或者别的方法)。文本行被 spout 传给一个 bolt,再被 bolt 按单词切割。单词流又被传给另一个 bolt,在这里每个单词与一张政治人名列表比较。每遇到一个匹配的名字,第二个 bolt 为这个名字在数据库的计数加1。你可以随时查询数据库查看结果, 而且这些计数是随着数据到达实时更新的。所有组件(spouts和bolts)及它们之间的关系请参考拓扑图1-1

现在想象一下,很容易在整个 Storm 集群定义每个 bolt 和 spout 的并行性级别,因此你可以无限的扩展你的拓扑结构。很神奇,是吗?尽管这是个简单例子,你也可以看到 Storm 的强大。

有哪些典型的 Storm 应用案例?

数据处理流

正如上例所展示的,不像其它的流处理系统,Storm 不需要中间队列。

连续计算

连续发送数据到客户端,使它们能够实时更新并显示结果,如网站指标。

分布式远程过程调用

频繁的 CPU 密集型操作并行化。

Storm 组件

对于一个Storm集群,一个连续运行的主节点组织若干节点工作。

在 Storm 集群中,有两类节点:主节点 master node 和工作节点 worker nodes。主节点运行着一个叫做 Nimbus 的守护进程。这个守护进程负责在集群中分发代码,为工作节点分配任务,并监控故障。Supervisor守护进程作为拓扑的一部分运行在工作节点上。一个 Storm 拓扑结构在不同的机器上运行着众多的工作节点。

因为 Storm 在 Zookeeper 或本地磁盘上维持所有的集群状态,守护进程可以是无状态的而且失效或重启时不会影响整个系统的健康(见图1-2)

在系统底层,Storm 使用了 zeromq(0mq, zeromq(http://www.zeromq.org))。这是一种先进的,可嵌入的网络通讯库,它提供的绝妙功能使 Storm 成为可能。下面列出一些 zeromq 的特性。

  • 一个并发架构的 Socket 库
  • 对于集群产品和超级计算,比 TCP 要快
  • 可通过 inproc(进程内), IPC(进程间), TCP 和 multicast(多播协议)通信
  • 异步 I / O 的可扩展的多核消息传递应用程序
  • 利用扇出(fanout), 发布订阅(PUB-SUB),管道(pipeline), 请求应答(REQ-REP),等方式实现 N-N 连接

NOTE: Storm 只用了 push/pull sockets

Storm 的特性

在所有这些设计思想与决策中,有一些非常棒的特性成就了独一无二的 Storm。

  • 简化编程:如果你曾试着从零开始实现实时处理,你应该明白这是一件多么痛苦的事情。使用 Storm,复杂性被大大降低了。
  • 使用一门基于 JVM 的语言开发会更容易,但是你可以借助一个小的中间件,在 Storm 上使用任何语言开发。有现成的中间件可供选择,当然也可以自己开发中间件。
  • 容错:Storm 集群会关注工作节点状态,如果宕机了必要的时候会重新分配任务。
  • 可扩展:所有你需要为扩展集群所做的工作就是增加机器。Storm 会在新机器就绪时向它们分配任务。
  • 可靠的:所有消息都可保证至少处理一次。如果出错了,消息可能处理不只一次,不过你永远不会丢失消息。
  • 快速:速度是驱动 Storm 设计的一个关键因素
  • 事务性:You can get exactly once messaging semantics for pretty much any computation. 你可以为几乎任何计算得到恰好一次消息语义。
Storm 起步
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }