Storm storm简介(一)
1、介绍
Storm的使用场景非常广泛,比如实时分析、在线机器学习、分布式RPC、ETL等。Storm非常高效,再一个多节点集群上每秒中可以轻松处理上百万的消息。Storm还具有良好的可扩展性和容错性以及保证数据可以至少被处理一次等特性。
Storm的组成拓扑图就是Storm的应用(Topology),其中的水龙头是Spout,用来源源不断的读取消息并发从出去,水管的每一个转接口就是一个Bolt,通过Stream分组的策略转发消息流。
2、集群组成
Storm的集群表面上看和Hadoop的集群非常像。但是再Hadoop上运行的是MapReduce的作业(Job),而在Storm上运行的是Topolopy。Storm和Hadoop一个非常关键的区别是Hadoop的MapReduce作业最中会结束,而Storm的Topolopy会一直运行(除非显式3的杀掉)。
3、Storm和Hadoop对比
如果说批处理的Hadoop需要一桶桶地搬走水,那么Storm就好比自来水水管,只要预先接好水管,然后打开水龙头,水就源源不断的流出来了,即就会被实时的处理。
在Storm的集群中有两种节点:主节点(Master Node)Nimbus和工作节点(Worker Node)Supervisor。Nimbus的作用类似于Hadoop中的JobTracker,Nimbus负责在集群中分发代码,分配工作给机器,并且监控状态。每个工作节点上运行一个Supervisor进程(类似于TaskTracker)Supervisor会监听Nimbus分配给那台机器的工作,根据需要启动/关闭具体定位Worker进程。每个Worker进程执行一个具体的Topology,Worker进程中执行线程称为Executor,可以有一个或者多个。每个Excetor中又可以包含一个或着多个Task。Task为Storm中最小的处理单元。一个运行的Topolopy由运行在一台或者多台工作节点上的Worker进程来完成具体的业务执行。Storm组件和Hadoop组件的比对如下:
Storm组件和Hadoop组件对比
角色 Storm Hadoop
Nimbus JobTracker
Supervisor TaskTracker
Worker Child
Topolopy Job
Spout/Bolt Map/Reduce
Nimbus和Supervisor之间的通信依靠Zookeeper完成,并且Nimbus进程和Supervisor都是快速失败(fail-fast) 和无状态的,所有的状态要么在zookeeper里面,要么在本地磁盘上,这也就意味着你可以用kill -9 来杀死Nimbus和Supervisot进程,然后再重启它们,它们可以继续工作,就好像都没有发生过似的。这个设计使得Storm具有非常高的稳定性。其基本机构见下图:
Storm整体架构
4、Storm中的核心概念
Storm中的核心基本概念主要包含:Topology、Nimbus、Supervisor、Worker、Executor、Task、Spout、Blot、Tuple、Stream、Stream分组(grouping)等。
Storm组件基本概念
组件 | 概念 |
Topolopy |
一个实时计算应用程序逻辑上被封装在Topolopy对象中,类似Hadoop中的作业,与作用不同的是Topolopy一直运行直到显式的杀死 |
Nimbus | 负责资源分配和任务调度,类似Hadoop中的JobTasker |
Supervisor | 负责接受Nimbus分配的任务,启动和停止属于自己的Worker进程,类似与Hadoop中的TaskTracker |
Worker | 运行具体处理的组件逻辑的进程 |
Executor | Storm0.8之后,Executor为Worker进程中的具体的物理线程,同一个Spout/Bolt的Task可能会共享一个物理线程,一个Executor中只能运行隶属于同一个Spout/Bolt的Task |
Task | 每一个Spout/Bolt具体要做的工作,也是各个节点之间进行分组的的单位 |
Spout | 在Topolopy中产生源数据流的组件,通常Spout获取数据源的数据(如,Kafka、MQ等读取数据),然后调用nextTuple函数,发射数据供Bolt消费。 |
Bolt | 在Topolopy中接受Spout的处理组件。Bolt可以执行过滤、函数操作、合并、写数据库等操作,Bolt在接收到消息后会调用execute函数,用户可以在其中执行自己想要的操作。 |
Tuple | 消息传递的基本单元 |
Stream | 源源不断传递的Tuple组成了Stream |
Stream分组 | 即消息的分区(partition)方法,Storm中提供若干种实用的分组方式,包括Shuffle、Fields、All、Global、None、Direct和Local or Shuffle等 |
5、Storm中内置的7中Grouping分组方式,也可以通过实现CustomStreamGrouping接口来定义自己的分组。
(1)Shuffle分组:Task中的数据随机分配,可以保证同一级Bolt上的每个Task处理的Tuple数量一致,如图:
(2)Fields分组:根据Tuple中的某一个Field或者多个Field的值来划分。比如Stream根据user-id的值来分组,具有相同user-id值的Tuple会被分发到相同的Task中,如图,具有不同user-id值的Tuple可能会被分发到其他Task中。比如user-id为1的Tuple都会分发给Task1,user-id为2的Tuple可能在Task1上也可能在Task2上,但是同时只能在一个Task上。
(3)All分组:所有的Tuple都会到分发到所有的Task上,如图:
(4)Global分组:整个Stream会选择一个Task作为分发的目的地,通常是具有最新ID的Task如下图:
(5)None分组:也就是你不关心如何在Task中做Stream的分发,目前等同于Shuffle分组。
(6)Direct分组:这是一种特殊分组方式,也就是产生数据的Spout/Bolt自己明确决定这个Tuple被Bolt的哪些Task所消费。如果使用Direct分组,需要使用OutputCollector的emitDirect方法来实现。
(7)Local or Shuffle分组:如果目标Bolt中的一个或者多个Task和当前产生数据的Task在同一个Worker进程中,那么就走内部的线程通信,将tuple直接发给当前Worker进程中的目的Task。否则,同Shuffle分组。
6、Storm的可靠性
Storm允许用户在Spout中发射一个新的Tuple时为其指定一个MessageId,这个MessageId可以是任意的Object对象。多个Stream Tuple可以共用同一个MessageId表示这多个Stream Tuple对用户来说是同一个消息单元。Storm的可靠性是指Storm会告知用户每一个消息单元是否在一个指定的时间内被完全处理。完全处理的意思是该MessageId绑定的Stream Tuple以及由该Stream Tuple衍生的所有Tuple都经过了Topolopy中每一个应该到达的Bolt的处理。在Storm中,使用Acker来解决Tuple消息处理的可靠性问题。
7、Storm特性
总结起来,Storm具有如下优点。
(1)易用性:开发非常迅速,容易上手。只要遵守Topolopy、Spout和Bolt的编程规范即可开发出扩展性记号的应用。对于底层RPC、Worker之间冗余以及数据分流之类的操作,开发者完全不用考虑。
(2)容错行:Storm的守护进程(Nimbus、Supervisor等)都是无状态的,状态保存在Zookeeper中,可以随意重启。当Worker失效或机器出现故障时,Storm自动分配新的Worker替换失效的Worker。
(3)扩展性:当某一级处理单元速度不够,可以直接配置并发数,即可线性的扩展性能。
(4)完整性:采用Acker机制,保证数据不丢失;采用事务机制,保证数据准确性。