是什么?
一个开源的分布式实时计算系统。
功能
- 可靠地处理无限的数据流
- 可以实时处理数据
对于实时处理
实时处理一般流程
在Storm之前,进行实时处理是非常痛苦的事情: 需要维护一堆消息队列和消费者,他们构成了非常复杂的图结构。消费者进程从队列里取消息,处理完成后,去更新数据库,或者给其他队列发新消息。
问题所在
我们主要的时间都花在关注往哪里发消息,从哪里接收消息,消息如何序列化,真正的业务逻辑只占了源代码的一小部分。一个应用程序的逻辑运行在很多worker上,但这些worker需要各自单独部署,还需要部署消息队列。最大问题是系统很脆弱,而且不是容错的:需要自己保证消息队列和worker进程工作正常。
storm的实时处理
Storm完整地解决了这些问题。它是为分布式场景而生的,抽象了消息传递,会自动地在集群机器上并发地处理流式计算,让你专注于实时处理的业务逻辑。
Storm的特点
- 编程简单:开发人员只需要关注应用逻辑,而且跟Hadoop类似,Storm提供的编程原语也很简单
- 高性能,低延迟:可以应用于广告搜索引擎这种要求对广告主的操作进行实时响应的场景。
- 分布式:可以轻松应对数据量大,单机搞不定的场景
- 可扩展: 随着业务发展,数据量和计算量越来越大,系统可水平扩展
- 容错:单个节点挂了不影响应用
- 消息不丢失:保证消息处理
- Storm处理速度很快:每个节点每秒钟可以处理超过百万的数据组。
它是可扩展(scalable),容错(fault-tolerant),保证你的数据会被处理,并且很容易搭建和操作。
使用storm注意点
Storm不是一个完整的解决方案。
使用Storm时你需要关注以下几点:
- 如果使用的是自己的消息队列,需要加入消息队列做数据的来源和产出的代码
- 需要考虑如何做故障处理:如何记录消息队列处理的进度,应对Storm重启,挂掉的场景
- 需要考虑如何做消息的回退:如果某些消息处理一直失败怎么办
Storm的使用场景及应用
跟Hadoop不一样,Storm是没有包括任何存储概念的计算系统。
这就让Storm可以用在多种不同的场景下:
非传统场景下数据动态到达或者数据存储在数据库这样的存储系统里(或数据是被实时操控其他设备的控制器(如交易系统)所消费)
Storm有很多应用:
- 实时分析
- 在线机器学习(online machine learning),
- 连续计算(continuous computation),
- 分布式远程过程调用(RPC)、ETL等。
storm与Hadoop
hadoop
hadoop实质上是一个批处理系统,专注于大数据的批量处理。数据存储在hadoop文件系统HDFS上并在处理的时候分发到集群中的各个节点。数据处理完成,产生的数据放回到HDFS上。
storm
storm上构建拓扑处理的是持续不断的流式数据。这些处理过程不会终止,会持续处理到达的数据。
对比一下
- Hadoop处理的是静态的数据
- storm处理的是动态的连续的数据
storm一个复杂事件处理系统
是什么?
复杂事件处理系统通常是面向检测和计算的,这两个都可以通过用户自定义的算法在storm中实现。
作用
复杂事件处理可以用来从大量事件中区分出有意义的事件,然后对这些事件实时处理。
storm模型
storm实现了一个大数据流模型,这个模型中数据不断流经一个由很多转换实体构成的网络。
流与元组
一个数据流的抽象叫做流(stream),流是无限的元组(Tuple)序列。
元组就像一个可以表示标准数据类型(例如int,float和byte数组)和用户自定义类型(需要额外序列化代码的)的数据结构。
每个流由一个唯一的ID来标示的,这个ID可以用来构建拓扑中各个组件的数据源。
元组通过流经不同的转换实体而被处理。
比较storm和hadoop
- Storm对数据输入的来源和输出数据的去向没有做任何限制。可以使用任意来源的数据输入和任意的数据输出,只要你实现对应的代码来获取/写入这些数据就可以。
- Hadoop是需要把数据放到自己的文件系统HDFS里的
概念
- 拓扑(Topologies)
- 元组(Tuple)
- 流(Streams)
- Spouts(喷嘴)
- Bolts
- 任务(Tasks)
- 组件(Component)
- 流分组(Stream groupings)
- 可靠性(Reliability)
- Workers(工作进程)
拓扑(Topologies)
一个Storm拓扑打包了一个实时处理程序的逻辑。
一个Storm拓扑跟一个MapReduce的任务(job)是类似的。
区别于MapReduce
- MapReduce任务最终会结束
- 拓扑会一直运行(当然直到你杀死它)。
一个拓扑是一个通过流分组把Spout和Bolt连接到一起的拓扑结构。
一个拓扑就是一个复杂的多阶段的流计算。
元组(Tuple)
元组是Storm提供的一个轻量级的数据格式,可以用来包装你需要实际处理的数据。
元组是一次消息传递的基本单元。
一个元组是一个命名的值列表,其中的每个值都可以是任意类型的。
元组是动态地进行类型转化的–字段的类型不需要事先声明。
在Storm中编程时,就是在操作和转换由元组组成的流。
通常,元组包含整数,字节,字符串,浮点数,布尔值和字节数组等类型。
要想在元组中使用自定义类型,就需要实现自己的序列化方式。
流(Streams)
流是Storm中的核心抽象。
一个流由无限的元组序列组成,这些元组会被分布式并行地创建和处理。
通过流中元组包含的字段名称来定义这个流。
每个流声明时都被赋予了一个ID。只有一个流的Spout和Bolt非常常见,所以OutputFieldsDeclarer提供了不需要指定ID来声明一个流的函数(Spout和Bolt都需要声明输出的流)。这种情况下,流的ID是默认的“default”。
Spouts
Spout(喷嘴)是Storm中流的来源。
通常Spout从外部数据源,如消息队列中读取元组数据并吐到拓扑里。
Spout可以是可靠的(reliable)或者不可靠(unreliable)的。
- 可靠的Spout能够在一个元组被Storm处理失败时重新进行处理
- 非可靠的Spout只是吐数据到拓扑里,不关心处理成功还是失败了。
Spout可以一次给多个流吐数据。此时需要通过OutputFieldsDeclarer的declareStream函数来声明多个流并在调用SpoutOutputCollector提供的emit方法时指定元组吐给哪个流。
spouts函数
Spout中最主要的函数是nextTuple,Storm框架会不断调用它去做元组的轮询。
如果没有新的元组过来,就直接返回,否则把新元组吐到拓扑里。
nextTuple必须是非阻塞的,因为Storm在同一个线程里执行Spout的函数。
Spout中另外两个主要的函数是ack和fail。当Storm检测到一个从Spout吐出的元组在拓扑中成功处理完时调用ack,没有成功处理完时调用fail。只有可靠型的Spout会调用ack和fail函数。
组件(Component)
组件(component)是对Bolt和Spout的统称
Workers(工作进程)
拓扑以一个或多个Worker进程的方式运行。每个Worker进程是一个物理的Java虚拟机,执行拓扑的一部分任务。例如,如果拓扑的并发设置成了300,分配了50个Worker,那么每个Worker执行6个任务(作为Worker内部的线程)。Storm会尽量把所有的任务均分到所有的Worker上。