前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Storm 稳定态

Storm 稳定态

作者头像
Meet相识
发布2018-09-12 17:07:24
1.1K0
发布2018-09-12 17:07:24
举报
文章被收录于专栏:技术专栏

1.Task的分配

假设一个topology有4个worker,2个spout,2个bolt。spout1有4个task,spout2有2个task,bolt1有4个task,bolt2有4个task。(默认一个task对应一个Executor)

storm会为每个task顺次分配taskid,task分配情况如下:

spout1

t0 t1 t2

spout2

t3 t4

bolt1

t5 t6 t7 t8

bolt2

t9 t10 t11 t12

而每个task会被顺次分配到每一个worker下面,这个topology的结构如下:

image.png

2. Spout读取Kafka的逻辑

Kafka是有分区的,spout读取kafaka的partition的过程和task分配的过程类似,也是顺次分配。

继续上面的例子,假如spout1读取的kafka的topic1有3个partition,则每个task读取一个partition,他们之间并行处理,互不干扰。

image.png

由于kafka的数量是动态增加的,加入这时候又多了一个partition,则partition数大于spout的task数,这时候顺次排列,应该有task-0读取partition-4

image.png

如果此时partition-3被下掉了,则task-2会空余出来

注意由于task并行的互不干扰的处理自己对应的task,当task数大于partition数的时候,多出来的task并不会去和其他task共同处理一个partition,而是会保持空闲状态

image.png

3. Storm的at least once语义 {#id-3.Storm的atleastonce语义}

Storm的语义是at least once(至少处理一次)语义做的是最好的。at most once和tradient的state等其他语义用的并不多,这里不做讨论。

Spout在读取kafka的数据的时候,会将offset(偏移量)记录到zookeeper里面,但是由于spout读取kafka的数据并不是有序的,所以偏移量不能保证记录到所有已经正常处理的数据,

所以他的offset只会记录到拥有最小间隔的最大连续处理量的位置

image.png

如上图,加入在这个时候tuple1-20,24-30,35-40都已经处理了,但是由于20-24,30-35之间间断了,而最大的连续处理了是tuple1-20,所以如果此时worker或者spout的executor挂了,

这时的offset只能寄到tuple20的位置,当重启的时候,只能从tuple20的位置继续往下处理,这时tuple24-30,35-40会又被处理一次(被处理了两次),所以Storm的支持的语义是at least once(至少处理一次)。

正因为如此,我们需要在业务逻辑处理中考虑到这一点--我们的数据可能会被重复多次发送

4.Spout和Bolt之间的数据流

spout的task将数据发给哪个bolt,和bolt的task之间的数据发送,是由grouping决定的。但是数据的传输是以worker为单位的。

对于Spout发送的每一个tuple,都会记录他的发送者是谁,接受者是谁,但是真实的数据传输是由worker来完成的。

每一个Spout和Bolt都会有一个发送队列和接收队列,spout处理完数据放入自己的发送队列,bolt不断的从spout的发送队列里拿数据放到接受队列

小结

Storm稳定态里的数据流动主要包括以下几类:

  1. spout读取kafka
    1. spout向zookeeper中读写偏移量
    2. spout读取kafka的数据。会受kafka分区数和spout并发数的影响,这些配置修改后,会出发rebalance,将任务分配情况重新写入zookeeper,然后worker重新拉取配置。重新分配之后:
      1. 如果某个spout的task之前没有读取过当前分配的partition,或者刚启动的时候,会从zookeeper里读取offset
      2. spout正常读取某个partition,会在内存里记录哪个tuple被ack了,哪个被fail了,哪个还未超时。然后从最小间隔的连续的偏移量读取,过滤掉被ack的和未超时的
  2. spout发送数据到bolt,bolt与bolt之间的数据流动
    1. spout发送数据给其他worker,会记录当前的taskid,接受者的taskid,发送给哪个worker。然后把发送消息写入发送队列里,又worker进行发送
    2. worker从接受队列里读取数据给bolt
  3. 心跳汇报
    1. worker要定期的写心跳到zoopkeer,汇报对象是worker粒度的,而不是bolt,spout这些组件,所以如果某个bolt被阻塞了或者假死了,nimbus并不会知道。
    2. superviors定期写心跳到zookeeper
    3. nimbus统一读取汇总心跳信息(统一由nimbus读取,保证分布式一致性)
  4. zookeeper集群之间的数据流动(非此次总结重点)
  5. nimbus和superviors之间的数据流动,如nimbus像superviors分配worker和task,superviors拉取jar包,依赖等(非此次总结重点)

抛一个点:上游往下游发送数据会不会有阻力拖住发送的速度,都有什么方式:

  1. Config.setMaxSpoutPending() 设置一个spout最多只能发送n条数据出去(最多只能有1000条数据在外面),超过了这个数量就不发了
  2. back press:https://blog.csdn.net/qq_21125183/article/details/80708142
  3. worker之间的NIO 如果下游未处理数据量太多,会导致下游不在读取数据,此时上游写不进来。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.08.21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.Task的分配
  • 2. Spout读取Kafka的逻辑
  • 3. Storm的at least once语义 {#id-3.Storm的atleastonce语义}
  • 4.Spout和Bolt之间的数据流
  • 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档