一、Hadoop VS Storm
二、集群架构
三、JStorm组件
四、并发机制
五、数据流分发
六、总结
一、Hadoop VS Storm
当说到大数据时,很多人都会想到Hadoop,当然除了Hadoop,还有其他很多优秀的解决方案,Storm就是其中之一。Hadoop擅长离线分析,而Storm是用流数据处理技术,解决实时分析、在线机器学习、持续计算、分布式RPC等业务场景。Storm核心代码是用Clojure开发的,JStorm是alibaba开源的Java版,JStorm在资源调度、可用性及稳定性等做了持续优化,并且提供了实时计算的完整解决方案。
离线计算占据了大数据行业很大比重,Hadoop也成了大数据事实上的标准,但随着业务场景越来越多,对实时、低延迟的要求也越来越高,流式计算就是解决这些问题的最佳方案。流式计算的思想是以数据流的形式实时接收持续生成的无穷尽的数据,数据像流水一样被计算系统处理,一旦计算任务启动,任务会一直运行,除非被用户主动kill掉。
二、集群架构
Storm集群是一个主从架构:有一个主节点和多个从节点。主节点和从节点的状态信息都保存在zookeeper集群,nimbus、supervisor、worker通过心跳机制把当前状态保存到zk。
Nimbus:一个jstorm集群有一个Nimbus节点,负责Topology代码分发到supervisor节点、Task任务分发、supervisor监控、topology监控等。nimbus的一个后台线程(TopologyAssign类)会分配任务到指定supervisor的work,分配的任务信息写在zookeeper,supervisor watch znode,这样supervisor就可以执行nimbus传递的命令 。同时numbus根据supervisor、work写入到znode的信息,监控supervisor、task的运行情况。nimbus是无状态的,意味着可以快速失败,如果nimbus挂掉了,不影响集群运行,只是不能执行submit topology、kill topology、rebanlance等操作。
Supervisor:一个集群有一个或多个supervisor节点,supervisor控制Worker的整个生命周期,负责worker进程的启动、停止,具体的实现类是SupervisorManger。supervisor也是无状态的,如果supervisor挂掉,不影响worker的运行。
Zookeeper:提供协调集群服务、不进行消息传输,nimbus、supervisor、worker、topology的状态信息都会保存在ZK。例如nimbus通过watch znode操作,能够监控到superviosr运行情况
nimbus、supervisor必须在监督下运行,例如使用daemontools、monit等监控后台进程,这样当进程异常终止时能及时重启,保证集群的可用性。
三、JStorm组件
tuple:tuple是一个定长的、有序的键值对列表;stream是由tuple组成的无界序列。获得tuple中的value,可以通过索引或元素的key。
Topology:JStorm的计算逻辑称为Topology,一个Topology就是一个job,Topology又由spout和bolt组成
spout:是Topology连接外部数据源的收集器,外部数据源可以是日志文件、消息队列、数据库等,然后把数据封装成tuple,并发送(emit)给下游bolt。读取数据源的消息是一个主动行为,jstorm框架循环调用nextTuple方法,如果没有读取到消息、或没tuple去emit时,可以休眠一段时间,减少cpu不必要的开销
bolt:bolt是实际的业务计算单元,可以从一个或多个spout或bolt订阅数据流,接收到的数据经过计算后发送给下游bolt,也可以不发送,如果不发送,就表示数据流处理结束。topology中消息传递是用的生成者-消费者模式,底层用Disruptor实现的。
spout和bolt之间的数据流订阅关系,形成了一个有向无环图。
四、并发机制
Worker:worker是实际执行任务的JVM进程,一个work占用一个端口号,配置文件中supervisor.slots.ports的数量,即是supervisor中可以启动的最大work数量。worker挂掉时,supervisor会把它重启,如果重启时连续失败导致nimbus通过心跳机制检测不到worker的存活(基于保存在zookeeper中worker状态信息判断),nimbus会把这个worker的任务重新分配给其他supervisor。如果worker挂掉,worker中的数据也随着丢失了(JVM内存中的数据)。
Executor:是worker启动的执行线程,一个worker可以启动多个Executor
Task:task是实际的数据处理单元,一个Task就是一个spout或bolt的实例
在topology的整个生命周期里,一个组件(spoult/bolt)的task数是固定的,但executor的数量是可以随时间改变的,可以对正在执行的topology动态调整executor数(rebalance命令)。
五、数据流分发
数据流中的tuple如何在topology的组件中分发,是在声明topology时显示的定义的,也就是说topology明确定义了组件间数据流的订阅关系。jstorm内置的六种分发模式:
Shuffle grouping:随机分发tuple给bolt的各个task,storm会尽量保证每个bolt的实例收到相同数量tuple;task处理的数据是均衡分配的
Fields grouping:根据tuple中指定字段的值分组,所有字段值相同的tuple会分发给bolt的同一个实例;当需要在task内部统计某个字段的数量,这种方式非常有帮助。如果数据流中分组字段的值不是均匀分布的,会引起task热点:有的task收到的tuple数多,有的收到的tuple数少。
All grouping:所有tuple都分发给所有bolt的实例:每个订阅了数据流的task都会收到所有的tuple。
Globle grouping:很All grouping分发方式相反:所有的tuple都只会分发到唯一一个task上。当使用这种方式时,再设置bolt的并发度就毫无意义,因为所有的tuple都只会分发到同一个task上;也会引起集群中某个JVM或服务器出现性能瓶颈问题
Direct grouping:消息发送发指定了消息订阅方的哪个task处理这个消息。
六、总结
storm是一个分布式、可靠的流数据处理系统,基于提供的API实现业务层数据处理,不需要关注底层实现细节,在项目上很易于实现。
加入KETTLE技术交流群,分享学习心得,一起共同进步。
QQ群:452881901,扫下方二维码快速加群:
点击下方阅读原文,继续阅读《MongoDB分片实践》