Storm例题:双十一订单

4.Storm例题,双十一订单题

订单编号-----时间戳----商品编号----数量----店铺ID----单价----用户ID

订单编号----用户ID+时间戳

时间戳-----

商品编号-----店铺编号+随机数【10】

店铺iD----随机生成2位数字【10-99】

单价【1-1000】

用户ID[UUID]前20位

需求:

  • 进行了多少次交易?
  • 累积到现在总的交易额?
  • 统计每种商品卖出去多少件商品?
  • 统计每个店铺交易额?
  • 每个用户的消费金额?

程序如下:

  • ShoppingCountSpout:模拟上述数据的结构

    package com.gcc.shoppingCount;
    
    import org.apache.storm.spout.SpoutOutputCollector;
    import org.apache.storm.task.TopologyContext;
    import org.apache.storm.topology.OutputFieldsDeclarer;
    import org.apache.storm.topology.base.BaseRichSpout;
    import org.apache.storm.tuple.Fields;
    import org.apache.storm.tuple.Values;
    
    import java.util.Map;
    import java.util.Random;
    import java.util.UUID;
    
    public class ShoppingCountSpout extends BaseRichSpout {
        //声明一个SpoutOutputcollector 对象 用于发送数据
        private SpoutOutputCollector collector;
        //创建一个数组存放需要发送的数据
        private String[] array={"hello world","hello gcc","hello hi welcome to world"};
    
        private Random random=new Random();
    
        @Override
        public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
            this.collector=collector;
        }
    
        /**
         * 重复调用这一个方法从源数据获取一条记录
         * 我们根据业务需求近期进行封装,然后通过SpoutOutputCollector 发送给下一个Bolt
         *
         */
        @Override
        public void nextTuple() {
            //获取本次需要发送的字符串
            //用户编号
            String userID= UUID.randomUUID().toString().replace("-","").substring(0,20);
            //时间戳
            long currentTimeMillis = System.currentTimeMillis();
            //订单编号
            String orderID=userID+currentTimeMillis;
            //店铺编号
            int shopID= (int) (Math.random()*90+10);
            //商品编号
            String goodID=String.valueOf(shopID)+(int)Math.random()*10;
            //单价
            int price= (int)(Math.random()*1000+1);
            //数量
            int num= (int)(Math.random()*100+1);
            String line=orderID+"--"+currentTimeMillis+"--"+goodID+"--"+num+"--"+shopID+"--"+price+"--"+userID;
    //        System.out.println("ShoppingCountSpout.nextTuple---"+line);
            collector.emit(new Values(line));
                //限制传输速度
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 定义输出值对应的属性
         * @param declarer
         */
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
    
            declarer.declare(new Fields("line"));
        }
    }
    
    
  • 切分:按照商品id划分

    package com.gcc.shoppingCount;
    
    import org.apache.storm.topology.BasicOutputCollector;
    import org.apache.storm.topology.OutputFieldsDeclarer;
    import org.apache.storm.topology.base.BaseBasicBolt;
    import org.apache.storm.tuple.Fields;
    import org.apache.storm.tuple.Tuple;
    import org.apache.storm.tuple.Values;
    
    
    public class GoodSplitBolt extends BaseBasicBolt {
    
        /**
         * 处理数据的业务逻辑
         * 切分 并发送给count统计,按照S商品id划分
         *
         * @param input
         * @param collector
         */
        @Override
        public void execute(Tuple input, BasicOutputCollector collector) {
            //获取单词
            System.out.println("priceCountBolt--execute:"+input.getStringByField("line"));
            String[]words=input.getStringByField("line").split("--");
            collector.emit(new Values(words[3],words[2]));
        }
    
        /**
         * 如果需要向下传递数据,需要提前定义数据格式
         * @param declarer
         */
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
            declarer.declare(new Fields("num","goodid"));
        }
    }
    
    
  • 统计每个商品卖出的件数

    package com.gcc.shoppingCount;
    
    import org.apache.storm.topology.BasicOutputCollector;
    import org.apache.storm.topology.OutputFieldsDeclarer;
    import org.apache.storm.topology.base.BaseBasicBolt;
    import org.apache.storm.tuple.Tuple;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    public class GoodCountBolt extends BaseBasicBolt {
    
        //容器计算每个商品卖出去多少件
        private Map<String,Integer>map =new HashMap<>();
    
        /**
         * 处理数据的业务逻辑
         * 进行了多少次交易
         * 累计到现在的总交易额
         * @param input
         * @param collector
         */
        @Override
        public void execute(Tuple input, BasicOutputCollector collector) {
            //获取单词
            String goodID=input.getStringByField("goodid");
            int num=Integer.parseInt(input.getStringByField("num"));
            System.out.println("goodCountBolt--execute: 商品编号"+goodID+"销量:" +num);
            if(map.containsKey(goodID)){
                int count=map.get(goodID);
                count+=num;
                map.put(goodID,count);
            }else{
                map.put(goodID,num);
            }
    
            System.out.println("goodCountBolt本次执行完,"+"商品id:"+goodID+"销量:"+map.get(goodID));
        }
    
        /**
         * 如果需要向下传递数据,需要提前定义数据格式
         * @param declarer
         */
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
        }
    }
    
    
  • 统计当前的总交易次数以及交易额

    package com.gcc.shoppingCount;
    
    import org.apache.storm.topology.BasicOutputCollector;
    import org.apache.storm.topology.OutputFieldsDeclarer;
    import org.apache.storm.topology.base.BaseBasicBolt;
    import org.apache.storm.tuple.Tuple;
    
    
    public class PriceCountBolt extends BaseBasicBolt {
        //声明一个容器 存在以前的统计结果
        private int count;
        private int allprice;
    
        /**
         * 处理数据的业务逻辑
         * 进行了多少次交易
         * 累计到现在的总交易额
         * @param input
         * @param collector
         */
        @Override
        public void execute(Tuple input, BasicOutputCollector collector) {
            //获取单词
            System.out.println("priceCountBolt--execute:"+input.getStringByField("line"));
            String[]words=input.getStringByField("line").split("--");
            allprice+=Integer.valueOf(words[3])*Integer.valueOf(words[5]);
            count++;
            System.out.println("priceCountBolt本次执行完,"+"总交易额:"+allprice+"总交易次数:"+count);
        }
    
        /**
         * 如果需要向下传递数据,需要提前定义数据格式
         * @param declarer
         */
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
        }
    }
    
    
  • 按照店铺ID进行划分

    package com.gcc.shoppingCount;
    
    import org.apache.storm.topology.BasicOutputCollector;
    import org.apache.storm.topology.OutputFieldsDeclarer;
    import org.apache.storm.topology.base.BaseBasicBolt;
    import org.apache.storm.tuple.Fields;
    import org.apache.storm.tuple.Tuple;
    import org.apache.storm.tuple.Values;
    
    
    public class ShopSplitBolt extends BaseBasicBolt {
    
        /**
         * 处理数据的业务逻辑
         * 切分 按照店铺id划分
         *
         * @param input
         * @param collector
         */
        @Override
        public void execute(Tuple input, BasicOutputCollector collector) {
            //获取单词
    //        System.out.println("ShopSplitBolt--execute:"+input.getStringByField("line"));
           String[]words=input.getStringByField("line").split("--");
            System.out.println("数量:"+words[3]+",单价:"+words[5]+",店铺id:"+words[4]);
              collector.emit(new Values(words[3],words[5],words[4]));
        }
    
        /**
         * 如果需要向下传递数据,需要提前定义数据格式
         * @param declarer
         */
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
            declarer.declare(new Fields("num","price","shopid"));
        }
    }
    
    
  • 统计每个店铺的总交易额

    package com.gcc.shoppingCount;
    
    import org.apache.storm.topology.BasicOutputCollector;
    import org.apache.storm.topology.OutputFieldsDeclarer;
    import org.apache.storm.topology.base.BaseBasicBolt;
    import org.apache.storm.tuple.Tuple;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    public class ShopCountBolt extends BaseBasicBolt {
    
        //容器计算每个店铺的总交易额度
        private Map<String,Integer>map =new HashMap<>();
    
        /**
         * 处理数据的业务逻辑
         * 进行了多少次交易
         * 累计到现在的总交易额
         * @param input
         * @param collector
         */
        @Override
        public void execute(Tuple input, BasicOutputCollector collector) {
            //获取单词
            String shopID=input.getStringByField("shopid");
            int num=Integer.parseInt(input.getStringByField("num"));
            int price=Integer.parseInt(input.getStringByField("price"));
            System.out.println("ShopCountBolt--execute: 店铺编号"+shopID+"销量:" +num+"单价:"+price);
            if(map.containsKey(shopID)){
                int sum=map.get(shopID);
                sum+=num*price;
                map.put(shopID,sum);
            }else{
                map.put(shopID,num*price);
            }
    
            System.out.println("ShopCountBolt本次执行完,"+"店铺id:"+shopID+",总交易额:"+map.get(shopID));
        }
    
        /**
         * 如果需要向下传递数据,需要提前定义数据格式
         * @param declarer
         */
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
        }
    }
    
    
  • 按照用户的id进行切分

    package com.gcc.shoppingCount;
    
    import org.apache.storm.topology.BasicOutputCollector;
    import org.apache.storm.topology.OutputFieldsDeclarer;
    import org.apache.storm.topology.base.BaseBasicBolt;
    import org.apache.storm.tuple.Fields;
    import org.apache.storm.tuple.Tuple;
    import org.apache.storm.tuple.Values;
    
    
    public class userSplitBolt extends BaseBasicBolt {
    
        /**
         * 处理数据的业务逻辑
         * 切分 按照用户id切分 计算用户的消费金额
         *
         * @param input
         * @param collector
         */
        @Override
        public void execute(Tuple input, BasicOutputCollector collector) {
            //获取单词
    //        System.out.println("ShopSplitBolt--execute:"+input.getStringByField("line"));
            String[] words = input.getStringByField("line").split("--");
            System.out.println("数量:" + words[3] + ",单价:" + words[5] + ",用户id:" + words[6]);
            collector.emit(new Values(words[3], words[5], words[6]));
        }
    
        /**
         * 如果需要向下传递数据,需要提前定义数据格式
         *
         * @param declarer
         */
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
            declarer.declare(new Fields("num", "price", "userid"));
        }
    }
    
    
  • 统计每个用户的总交易额

    package com.gcc.shoppingCount;
    
    import org.apache.storm.topology.BasicOutputCollector;
    import org.apache.storm.topology.OutputFieldsDeclarer;
    import org.apache.storm.topology.base.BaseBasicBolt;
    import org.apache.storm.tuple.Tuple;
    
    import java.util.HashMap;
    import java.util.Map;
    
    
    public class UserCountBolt extends BaseBasicBolt {
    
        //容器计算每个用户的消费金额
        private Map<String,Integer>map =new HashMap<>();
    
        /**
         * 处理数据的业务逻辑
         * @param input
         * @param collector
         */
        @Override
        public void execute(Tuple input, BasicOutputCollector collector) {
            //获取单词
            String userID=input.getStringByField("userid");
            int num=Integer.parseInt(input.getStringByField("num"));
            int price=Integer.parseInt(input.getStringByField("price"));
            System.out.println("UserCountBolt--execute: 用户编号"+userID+"购买数量:" +num+"单价:"+price);
            if(map.containsKey(userID)){
                int sum=map.get(userID);
                sum+=num*price;
                map.put(userID,sum);
            }else{
                map.put(userID,num*price);
            }
    
            System.out.println("UserCountBolt本次执行完,"+"用户id:"+userID+",总消费金额:"+map.get(userID));
        }
    
        /**
         * 如果需要向下传递数据,需要提前定义数据格式
         * @param declarer
         */
        @Override
        public void declareOutputFields(OutputFieldsDeclarer declarer) {
        }
    }
    
    
  • 设置拓扑结构

    package com.gcc.shoppingCount;
    
    import org.apache.storm.Config;
    import org.apache.storm.LocalCluster;
    import org.apache.storm.generated.StormTopology;
    import org.apache.storm.topology.TopologyBuilder;
    import org.apache.storm.tuple.Fields;
    
    public class ShoppingCountTopology {
        public static void main(String[] args) {
            //1.创建任务的拓扑图
            //创建topology的构建起
            TopologyBuilder topologyBuilder = new TopologyBuilder();
            //设置拓扑关系(Spout)
            topologyBuilder.setSpout("ShoppingCountSpout",new ShoppingCountSpout());
    
            //设置拓扑关系Bolt 计算交易次数以及交易额
            topologyBuilder.setBolt("priceCountBolt",new PriceCountBolt(),1).shuffleGrouping("ShoppingCountSpout");
            //设置拓扑关系Bolt 对每种商品的销量进行统计
            topologyBuilder.setBolt("goodSplitBolt",new GoodSplitBolt(),2).shuffleGrouping("ShoppingCountSpout");
            topologyBuilder.setBolt("goodCountBolt",new GoodCountBolt(),4).fieldsGrouping("goodSplitBolt",new Fields("goodid"));
    
            //统计每个店铺的交易额度
            topologyBuilder.setBolt("ShopSplitBolt",new ShopSplitBolt(),2).shuffleGrouping("ShoppingCountSpout");
            topologyBuilder.setBolt("ShopCountBolt",new ShopCountBolt(),4).fieldsGrouping("ShopSplitBolt",new Fields("shopid"));
    
            //统计每个用户的消费总金额
            topologyBuilder.setBolt("userSplitBolt",new userSplitBolt(),2).shuffleGrouping("ShoppingCountSpout");
            topologyBuilder.setBolt("UserCountBolt",new UserCountBolt(),4).fieldsGrouping("userSplitBolt",new Fields("userid"));
    
            //2.配置启动
            Config config = new Config();
           //创建Topology
            StormTopology topology = topologyBuilder.createTopology();
            //本地模式启动集群
            LocalCluster localCluster = new LocalCluster();
            localCluster.submitTopology("ShoppingCountTopology",config,topology);
    
    
        }
    }
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值