大数据(066)Storm【Storm计算模型】

一、Storm计算模型简介

        DAG计算模型,一个阶段接另一个阶段再接另一个阶段,在这个有向无环图里面可以灵活的组合,DAG是由Spout和bolt组合起来的,它们都是节点,边就是stream数据流,数据流里面的数据单元就是Tuple,而grouping呢就是数据流里面的数据如何做分发。

二、DAG模型介绍

         上图所示为DAG模型图,我们可以看到,每一个水龙头是一个Spout,是数据源。每一个闪电是一个bolt,负责处理数据。他们之间连线被分为一个个Tuple,是数据传输的最小单元。

        那为什么storm要用这种DAG呢,有向无环图呢,因为如果不用DAG,用MapReduce的话,等于你需要一个mapreduce接下一个mapreduce,而在这里呢,图上就相当于一个map接一个reduce再接一个reduce,很连贯的进行处理。

        这就是第一个好处,DAG有很多个阶段,可以进行灵活的装配,比如这里的bolt可以在这个应用被用到,也可以在另外的应用里面被用到。

        另外一个好处就是说,它能把数据真正的流起来,还是和hadoop的mapreduce对比,如果跑4个阶段,那就需要4个mapreduce任务,每一个阶段都得等上一个阶段结束,而流式处理4个阶段就可以同时处理。吞吐量的增加。一分钟处理一个,而mapreduce呢4分钟处理一个。而且整个DAG这个图是在内存里面的一个图,Spout和bolt都是在内存里面进行计算的,不会写入磁盘的,所以是非常高效的在运转。

2.1 Tuple

        storm使用tuple来作为它的数据模型。每个tuple是一堆值,每个值有一个名字,并且每个值可以是任何类型, 在我的理解里面一个tuple可以看作一个没有方法的java对象。总体来看,storm支持所有的基本类型、字符串以及字节数组作为tuple的值类型。你也可以使用你自己定义的类型来作为值类型, 只要你实现对应的序列化器(serializer)。一个Tuple代表数据流中的一个基本的处理单元,例如一条cookie日志,它可以包含多个Field,每个Field表示一个属性。

2.2 Stream

        Stream是storm里面的关键抽象。一个stream是一个没有边界的tuple序列。storm提供一些原语来分布式地、可靠地把一个stream传输进一个新的stream。比如: 你可以把一个tweets流传输到热门话题的流。

        storm提供的最基本的处理stream的原语是spout和bolt。你可以实现Spout和Bolt对应的接口以处理你的应用的逻辑。

        spout的流的源头。比如一个spout可能从Kestrel队列里面读取消息并且把这些消息发射成一个流。又比如一个spout可以调用twitter的一个api并且把返回的tweets发射成一个流。

        通常Spout会从外部数据源(队列、数据库等)读取数据,然后封装成Tuple形式,之后发送到Stream中。Spout是一个主动的角色,在接口内部有个nextTuple函数,Storm框架会不停的调用该函数。

        bolt可以接收任意多个输入stream, 作一些处理, 有些bolt可能还会发射一些新的stream。一些复杂的流转换, 比如从一些tweet里面计算出热门话题, 需要多个步骤, 从而也就需要多个bolt。 Bolt可以做任何事情: 运行函数, 过滤tuple, 做一些聚合, 做一些合并以及访问数据库等等。

        Bolt处理输入的Stream,并产生新的输出Stream。Bolt可以执行过滤、函数操作、Join、操作数据库等任何操作。Bolt是一个被动的角色,其接口中有一个execute(Tuple input)方法,在接收到消息之后会调用此函数,用户可以在此方法中执行自己的处理逻辑。

        spout和bolt所组成一个网络会被打包成topology, topology是storm里面最高一级的抽象(类似 Job), 你可以把topology提交给storm的集群来运行。

2.3 Grouping

        Grouping它是一个路由的策略,这个策略就做一件事,它决定一个Tuple发给下游某个bolt中n个并发中的哪一个Task,告诉topology如何在两个组件之间发送tuple, 定义一个topology的其中一步是定义每个bolt接收什么样的流作为输入。stream grouping就是用来定义一个stream应该如果分配数据给bolts上面的多个tasks。

        Storm里面有7种类型的stream grouping,你也可以通过实现CustomStreamGrouping接口来实现自定义流分组 。

        – 1. Shuffle Grouping
        随机分组,随机派发stream里面的tuple,保证每个bolt task接收到的tuple数目大致相同。

        – 2. Fields Grouping
        按字段分组,比如,按"user-id"这个字段来分组,那么具有同样"user-id"的tuple 会被分到相同的Bolt里的一个task, 而不同的"user-id"则可能会被分配到不同的task。

        – 3. All Grouping
        广播发送,对于每一个tuple,所有的bolts都会收到

        – 4. Global Grouping
        全局分组,整个stream被分配到storm中的一个bolt的其中一个task。再具体一点就是分配给id值最低的那个task。

        – 5. None Grouping
        不分组,这个分组的意思是说stream不关心到底怎样分组。目前这种分组和Shuffle grouping是一样的效果, 有一点不同的是storm会把使用nonegrouping的这个bolt放到这个bolt的订阅者同一个线程里面去执行(如果可能的话)。

        – 6. Direct Grouping
        指向型分组, 这是一种比较特别的分组方法,用这种分组意味着消息(tuple)的发送者指定由消息接收者的哪个task处理这个消息。只有被声明为 DirectStream 的消息流可以声明这种分组方法。而且这种消息tuple必须使用emitDirect 方法来发射。消息处理者可以通过 TopologyContext 来获取处理它的消息的task的id (OutputCollector.emit方法也会返回task的id)

        – 7. Local or shuffle grouping
        本地或随机分组。如果目标bolt有一个或者多个task与源bolt的task在同一个工作进程中,tuple将会被随机发送给这些同进程中的tasks。否则,和普通的Shuffle Grouping行为一致

三、Storm并发模型

        我们可以类比hadoop的mapreduce它的并发模型是怎样的,它的并发模型很简单,我的一个job有很多很多的Tasks,然后有1000个map,有100个reduce,一个集群呢有很多个节点,比如说有500个节点,那这个时候呢,就是我的每个节点上起一些map task,起一些reducetask,这个时候呢我的1000个map发到每个机器上去运行,每个maptask呢是一个进程,每个reduce task呢也是一个进程,hadoop它的并发模型很简单,就两级,它有很多机器,每个机器上面都有很多的task进程,task进程里面呢运行的就是我们mapreduce的函数。

        那storm呢,它的并发模型呢要复杂一些,接下来我们就看一看storm的并发模型是个什么样子的,首先我们看看它有哪些个层次,从大到小的话我们看它有这么5个层次,最简单的storm是个集群,cluster是个层次,第二个层次呢就是有比较明确的意义了,就是supervisor,supervisor对应的层级呢就是一个个的host,就是一个个的node,就是一个机器这个级别的,然后一个机器呢它又有很多的worker,worker其实就是对应process级别的,就是进程级别的,机器上跑几个进程,规定4个worker,就4个进程,每个worker里面跑着一个个executor,对应着的一个个线程,那接下来一个线程运行着一个或很多个task,一般很多情况下就一个task,当然了,有时候对应多个task,task就是最低级别的object,就是线程操作的就是一个个对象。

        我们举一个实际的例子来看一看一个并发模型在topology里面是什么样子的。

四、Storm数据传输

        下图为Storm数据传输示意图:

        1.executor执行spout.nextTuple()/bolt.execute(),emit tuple放入executor transfer queue
        2.executor transfer thread把自己transfer queue里面的tuple放到worker transfer queue
        3.worker transfer thread把transfer queue里面的tuple序列化发送到远程的worker
        4.worker receiver thread分别从网络收数据,反序列化成tuple放到对应的executor的receive queue
        5.executor receive thread从自己的receive queue取出tuple,调用bolt.execute() 

四、Storm ACK机制

        之前说过,Storm可以保证数据流完整的执行。这取决于Storm数据传递过程中的ACK机制。

        在Storm的一个Topology中,Spout通过SpoutOutputCollector的emit()方法发射一个tuple(源)即消息。而后经过在该Topology中定义的多个Bolt处理时,可能会产生一个或多个新的Tuple。源Tuple和新产生的Tuple便构成了一个Tuple树。当整棵树被处理完成,才算一个Tuple被完全处理,其中任何一个节点的Tuple处理失败或超时,则整棵树失败。如下图中的tuple tree。

        关于消息在storm中的超时默认为30秒,具体参看defaults.yaml中的topology.message.timeout.secs: 30的配置。同时,你也可以在定义topology时,通过conf.setMessageTimeoutSecs方法指定超时时间。

        Storm的Bolt有BasicBolt和RichBolt,在BasicBolt中,BasicOutputCollector在emit数据的时候,会自动和输入的tuple相关联,而在execute方法结束的时候那个输入tuple会被自动ack(有一定的条件)。

        在使用RichBolt时要实现ack,则需要在emit数据的时候,显示指定该数据的源tuple,即collector.emit(oldTuple, newTuple);并且需要在execute执行成功后调用源tuple的ack进行ack。 

取消ACK:

        如果可靠性对你来说不是那么重要 — 你不太在意在一些失败的情况下损失一些数据, 那么你可以通过不跟踪这些tuple树来获取更好的性能。

        有三种方法可以去掉可靠性:

        – 第一是把Config.TOPOLOGY_ACKERS 设置成 0. 在这种情况下, storm会在spout发射一个tuple之后马上调用spout的ack方法。也就是说这个tuple树不会被跟踪。

        – 第二个方法是在tuple层面去掉可靠性。 你可以在发射tuple的时候不指定messageid来达到不跟踪某个特定的spout tuple的目的。

        – 最后一个方法是如果你对于一个tuple树里面的某一部分到底成不成功不是很关心,那么可以在发射这些tuple的时候unanchor它们。 这样这些tuple就不在tuple树里面, 也就不会被跟踪了。

ACK算法:

        Acker的跟踪算法是Storm的主要突破之一,对任意大的一个Tuple树,它只需要恒定的20字节就可以进行跟踪。

        Acker跟踪算法的原理:acker对于每个spout-tuple保存一个ack-val的校验值,它的初始值是0,然后每发射一个Tuple或Ack一个Tuple时,这个Tuple的id就要跟这个校验值异或一下,并且把得到的值更新为ack-val的新值。那么假设每个发射出去的Tuple都被ack了,那么最后ack-val的值就一定是0。Acker就根据ack-val是否为0来判断是否完全处理,如果为0则认为已完全处理。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值