一、前述

Storm由数源泉spout到bolt时,可以选择分组策略,实现对spout发出的数据的分发。对多个并行度的时候有用。

二、具体原理

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

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

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

4. Global Grouping
全局分组,把tuple分配给task id最低的task 。

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

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

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

8.customGrouping
自定义,相当于mapreduce那里自己去实现一个partition一样。

总结:前4种用的多些,后面4种用的少些。

三、具体案例

Spout(产生数据):

package com.sxt.storm.grouping;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Map; import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichSpout;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Values; public class MySpout implements IRichSpout { private static final long serialVersionUID = 1L; FileInputStream fis;
InputStreamReader isr;
BufferedReader br; SpoutOutputCollector collector = null;
String str = null; @Override
public void nextTuple() {//真正发的逻辑
try {
while ((str = this.br.readLine()) != null) {
// 过滤动作
collector.emit(new Values(str, str.split("\t")[1]));//发出数据,一行和一行切分完后第二个字段。
}
} catch (Exception e) {
} } @Override
public void close() {//释放资源
try {
br.close();
isr.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
} @Override
public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {//初始化(方法只调用一次)
try {
this.collector = collector;
this.fis = new FileInputStream("track.log");
this.isr = new InputStreamReader(fis, "UTF-8");
this.br = new BufferedReader(isr);
} catch (Exception e) {
e.printStackTrace();
}
} @Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {//声明发出去的字段
declarer.declare(new Fields("log", "session_id"));
} @Override
public Map<String, Object> getComponentConfiguration() {
return null;
} @Override
public void ack(Object msgId) {
System.out.println("spout ack:" + msgId.toString());
} @Override
public void activate() {
} @Override
public void deactivate() {
} @Override
public void fail(Object msgId) {
System.out.println("spout fail:" + msgId.toString());
} }

Bolt:(处理单元)

package com.sxt.storm.grouping;

import java.util.Map;

import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple; public class MyBolt implements IRichBolt { private static final long serialVersionUID = 1L; OutputCollector collector = null;
int num = 0;
String valueString = null; @Override
public void cleanup() { } @Override
public void execute(Tuple input) {
try {
valueString = input.getStringByField("log");//通过fields接收数据 if (valueString != null) {
num++;
System.err.println(input.getSourceStreamId() + " " + Thread.currentThread().getName() + "--id="//打印当前进程名字
+ Thread.currentThread().getId() + " lines :" + num + " session_id:"//打印当前进程id
+ valueString.split("\t")[1]);//这行词的第二个字母
}
collector.ack(input);
// Thread.sleep(2000);
} catch (Exception e) {
collector.fail(input);
e.printStackTrace();
} } @Override
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
} @Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields(""));//声明空即可
} @Override
public Map<String, Object> getComponentConfiguration() {
return null;
} }

Main方法:

package com.sxt.storm.grouping;

import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.StormSubmitter;
import backtype.storm.generated.AlreadyAliveException;
import backtype.storm.generated.InvalidTopologyException;
import backtype.storm.topology.TopologyBuilder;
import backtype.storm.tuple.Fields; public class Main { /**
* @param args
*/
public static void main(String[] args) { TopologyBuilder builder = new TopologyBuilder(); builder.setSpout("spout", new MySpout(), 1);//拓扑名,数据源,并行度 builder.setBolt("bolt", new MyBolt(), 2).allGrouping("spout");//两个spot并行 所有都分发         //builder.setBolt("bolt", new MyBolt(), 2).shuffleGrouping("spout");// shuffleGrouping其实就是随机往下游去发,不自觉的做到了负载均衡
 
//builder.setBolt("bolt", new MyBolt(), 2).fieldsGrouping("spout", new Fields("session_id")); // fieldsGrouping其实就是MapReduce里面理解的Shuffle,根据fields求hash来取模        //builder.setBolt("bolt", new MyBolt(), 2).globalGrouping("spout"); // 只往一个里面发,往taskId小的那个里面去发送 // builder.setBolt("bolt", new MyBolt(), 2).noneGrouping("spout");   // 等于shuffleGrouping // Map conf = new HashMap();
// conf.put(Config.TOPOLOGY_WORKERS, 4);
Config conf = new Config();
conf.setDebug(false);
conf.setMessageTimeoutSecs(30); if (args.length > 0) {
try {
StormSubmitter.submitTopology(args[], conf, builder.createTopology());//集群方式
} catch (AlreadyAliveException e) {
e.printStackTrace();
} catch (InvalidTopologyException e) {
e.printStackTrace();
}
} else {
LocalCluster localCluster = new LocalCluster();
localCluster.submitTopology("mytopology", conf, builder.createTopology());// 本地模拟参数分别为名称,配置,构建拓扑结构。
} } }

 结果:

1. builder.setBolt("bolt", new MyBolt(), 2).allGrouping("spout");//两个spot并行 所有都分发

 2. builder.setBolt("bolt", new MyBolt(), 2).shuffleGrouping("spout")其实就是随机往下游去发,不自觉的做到了负载均衡

3.builder.setBolt("bolt", new MyBolt(), 2).fieldsGrouping("spout", new Fields("session_id")); // fieldsGrouping其实就是MapReduce里面理解的Shuffle,根据fields求hash来取模,相同的名称的fields分发到一个bolt里面。

4.builder.setBolt("bolt", new MyBolt(), 2).globalGrouping("spout"); // 只往一个里面发,往taskId小的那个里面去发送

企业中常用的也就是这几个!!!

【Storm篇】--Storm分组策略的更多相关文章

  1. 简单聊聊Storm的流分组策略

    简单聊聊Storm的流分组策略 首先我要强调的是,Storm的分组策略对结果有着直接的影响,不同的分组的结果一定是不一样的.其次,不同的分组策略对资源的利用也是有着非常大的不同,本文主要讲一讲loca ...

  2. Storm Grouping —— 流分组策略

    Storm Grouping: Shuffle Grouping :随机分组,尽量均匀分布到下游Bolt中 将流分组定义为混排.这种混排分组意味着来自Spout的输入将混排,或随机分发给此Bolt中的 ...

  3. storm 的分组策略深入理解(-)

    目录 storm的分组策略 根据实例来分析分组策略 common配置: Shuffle grouping shuffle grouping的实例代码 ShuffleGrouping 样例分析 Fiel ...

  4. 亿级流量场景下,大型架构设计实现【2】---storm篇

    承接之前的博:亿级流量场景下,大型缓存架构设计实现 续写本博客: ****************** start: 接下来,我们是要讲解商品详情页缓存架构,缓存预热和解决方案,缓存预热可能导致整个系 ...

  5. Storm流计算之项目篇(Storm+Kafka+HBase+Highcharts+JQuery,含3个完整实际项目)

    1.1.课程的背景 Storm是什么? 为什么学习Storm? Storm是Twitter开源的分布式实时大数据处理框架,被业界称为实时版Hadoop. 随着越来越多的场景对Hadoop的MapRed ...

  6. 【Storm篇】--Storm从初始到分布式搭建

    一.前述 Storm是一个流式处理框架,相比较于SparkStreaming是一个微批处理框架,hadoop是一个批处理框架. 二 .搭建流程 1.集群规划 Nimbus    Supervisor  ...

  7. 分布式流式处理框架:storm简介 + Storm术语解释

    简介: Storm是一个免费开源.分布式.高容错的实时计算系统.它与其他大数据解决方案的不同之处在于它的处理方式.Hadoop 在本质上是一个批处理系统,数据被引入 Hadoop 文件系统 (HDFS ...

  8. 【Storm】Storm实战之频繁二项集挖掘

    一.前言 针对大叔据实时处理的入门,除了使用WordCount示例之外,还需要相对更深入点的示例来理解Storm,因此,本篇博文利用Storm实现了频繁项集挖掘的案例,以方便更好的入门Storm. 二 ...

  9. 【Storm】Storm实战之频繁二项集挖掘(附源码)

    一.前言 针对大叔据实时处理的入门,除了使用WordCount示例之外,还需要相对更深入点的示例来理解Storm,因此,本篇博文利用Storm实现了频繁项集挖掘的案例,以方便更好的入门Storm. 二 ...

随机推荐

  1. Canal使用小结

    Canal使用小结 之前公司存在mysql数据同步mongo的需求,可以有多种实现方式,比如硬编码,发送消息等.公司选择的是Canal中间件,最近有空来研究下他的使用方式,对于mysql数据变更监听有 ...

  2. 部分手机浏览器存在将ajax请求当成广告过滤的情况,及解决方案

    我们发现h5页面在某些浏览器请求不到数据,经过排查,是浏览器的广告拦截模块搞的鬼. 通过删减参数,发现adtype和adnum参数去掉后,接口可以正常请求,开始以为是官方拦截关键词带有ad的参数,后来 ...

  3. php的运行机制

    php的解析过程是 apache -> httpd -> php5_module -> sapi -> php cgi (外部应用程序)只是用来解析php代码的 sapi中的其 ...

  4. 分分钟解决MySQL查询速度慢与性能差

    阅读本文大概需要 6 分钟. 一.什么影响了数据库查询速度 1.1 影响数据库查询速度的四个因素 1.2 风险分析 QPS: QueriesPerSecond意思是“每秒查询率”,是一台服务器每秒能够 ...

  5. Git ignore文件的用法

    这周为了往自己个人代码仓库里囤货,把在公司写的一些东西上传到了自己的GitHub代码仓库,手抖把测试用的日志也一并上传了.上传没多长时间就被运维找上门了,说commit里包含内网相关信息,要求删除.当 ...

  6. 图论之Dijkstra算法

    Dijkstra算法是图论中经典的最短路径算法之一,主要用于解决单源最短路径问题. 单源最短路径问题,即求某个源节点到其他各个节点的最短路径. Dijkstra算法采用了贪心算法的思想,如图求1号节点 ...

  7. 1.初识Node.js

    Node.js基础知识大汇总 1.下载并安装npm,检测安装是否成功(在命令行输入node -v,看是否会输出对应版本号) 2.写一个hello world 程序. (1).打开notepad,新建一 ...

  8. [Ubuntu]修改文件夹及所有子文件夹权限

    sudo chmod -R 777 FILE_NAME 使FILE_NAME文件或文件夹具有读写和执行的权限.

  9. Do Now 一个让你静心学习的APP——团队博客

    Do Now 一个让你静心学习的APP 来自油条只要半根团队的智慧凝聚的产物! 团队博客总目录: 团队作业第一周 团队作业第二周 Do Now -- 团队冲刺博客一 Do-Now-团队Scrum 冲刺 ...

  10. String.matches()的用法

    https://blog.csdn.net/victoryckl/article/details/6930409