storm对网站有关数据的统计以及多线程问题探讨

网站最常用的两个指标

pv: count(session_id)

uv: count(distinct session_id)

session_id是针对浏览器来说的,用户一进来就有

多线程下,注意线程安全问题

一:pv统计

方案分析

如何下是否可行:

1,定义static long PV,Synchronized控制累计操作

Synchronized和lock在单jvm下有效,但在多jvm下无效


可行的两个方案:

1,shuffleGrouping下,pv* Executor并发数

2,bolt1进行多并发局部汇总,bolt2单线程进行全局汇总

其中2最常用,因为存在你先按地区分,然后进行汇总的情况。就必须用fieldgrouping,不能用shufflegrouping

对于这种情况就比如下面两个代码

package visits;

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;
import backtype.storm.tuple.Values;

import java.util.Map;

/**
 * Created by Administrator on 2016/10/6.
 */
public class PVBolt1 implements IRichBolt {


    /*
    这种irichbolt形式就是成功的时候要显性的调ack方法
    失败的时候掉fail方法
     */
    private static final long serialVersionUID = 1L;
    OutputCollector collector = null;
    @Override
    public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {

        //初始化方法
        this.collector = outputCollector;
    }

    String logString = null;
    String sessionid = null;
    //static long Pv = 0;
    long Pv = 0;
    @Override
    public void execute(Tuple tuple) {
        logString = tuple.getString(0);
        sessionid = logString.split("\t")[1];
       /* *//*
        这种多线程下做计算我们还必须得有synchronized使它线程安全
        这样肯定就和单线程一样
        然而还是不够健全,因为synchronized和lock在单jvm下有效,单在多jvm下无效

         *//*
        synchronized (this){
            if(sessionid != null){
                Pv ++;
            }
        }*/

         //shuffleGrouping下,pv* Executor并发数就是统计的pv
        //因为shufflegrouping是平均分配,而我们有两个线程
        //
         if(sessionid != null){
             Pv ++;
         }

         collector.emit(new Values(Thread.currentThread().getId(),Pv));
        //System.out.println("pv = "+ Pv * 2);
        System.out.println("threadid = "+ Thread.currentThread().getId()+" : pv="+Pv);



    }

    @Override
    public void cleanup() {

    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {

        /*
        定义下输出类型
         */
        outputFieldsDeclarer.declare(new Fields("threadId", "pv"));
    }

    @Override
    public Map<String, Object> getComponentConfiguration() {
        return null;
    }
}
package visits;

import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Tuple;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by Administrator on 2016/10/6.
 * 汇总端得到的数据:每个线程发过来一个汇总数
 */
public class PVSumBolt implements IRichBolt {


    /*
    这种irichbolt形式就是成功的时候要显性的调ack方法
    失败的时候掉fail方法
     */
    private static final long serialVersionUID = 1L;
    Map<Long, Long> counts = new HashMap<Long, Long>();
    @Override
    public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {

    }


    //static long Pv = 0;
    long Pv = 0;
    @Override
    public void execute(Tuple tuple) {
        long threadID = tuple.getLong(0);
        long pv = tuple.getLong(1);
        counts.put(threadID, pv);
        long word_sum = 0;
        //获得总数,遍历counts的values,进行sum
        Iterator<Long> i = counts.values().iterator();
        while(i.hasNext()){
            word_sum += i.next();
        }

       /* *//*
        这种多线程下做计算我们还必须得有synchronized使它线程安全
        这样肯定就和单线程一样
        然而还是不够健全,因为synchronized和lock在单jvm下有效,单在多jvm下无效

         *//*
        synchronized (this){
            if(sessionid != null){
                Pv ++;
            }
        }*/

         //shuffleGrouping下,pv* Executor并发数就是统计的pv
        //因为shufflegrouping是平均分配,而我们有两个线程
        //


        System.out.println("pv = "+ Pv * 2);


    }

    @Override
    public void cleanup() {

    }

    @Override
    public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {

    }

    @Override
    public Map<String, Object> getComponentConfiguration() {
        return null;
    }
}
TopologyBuilder builder = new TopologyBuilder();

builder.setSpout("spout", new MySpout(), 1);
builder.setBolt("bolt", new PVBolt1(), 4).shuffleGrouping("spout");
/*
对单线程来讲,什么grouping都是一样的。。
 */
builder.setBolt("sumBolt", new PVSumBolt(), 1).shuffleGrouping("bolt");


线程不安全:

多线程处理的结果和单线程一样,一样就是安全,不一样就是不安全



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值