Storm+redis统计TopN

1、storm处理数据,数据准备。


    @Override
    public void execute(Tuple input) {
        Date date = new Date();
        LinkedList<String> redisKeyList = new LinkedList<>();
        try {
            // 主题id
            topicId = input.getStringByField("topicId");
            // 城市
            cityCode = input.getStringByField("cityCode");
            // 用户唯一标识
            userKey = input.getStringByField("userKey");
            // 用于辅助表的key
            tempMapKey = userKey + "_" + topicId;

            // 生成近7天的key(每次生成当前天数往前推7天的key的集合)
            for (int i= 0; i < 7 ;i++){
                String key = cityCode+"_uv_"+DateUtil.getDayN(date,i)+"_mostPopularTopic";
                redisKeyList.add(key);
            }
            // 写入数据到redis
            EsfTopNService.saveEsfTopNDataToRedis(redisKeyList,tempMapKey,topicId);

        }catch (Exception e) {
           e.printStackTrace();
        }finally {
            this.collector.ack(input);
        }
    }

2、把数据保存到redis中

/**
     * @功能描述: 保存topN的数据
     * @使用对象: 对外接口数据落地
     * @接口版本: 2.0.0
     * @创建作者: <a href="mailto:xxxx">zys</a>
     * @创建日期: 2019-11-20 10:00:41
     * @方法参数: [redisKeyList, tempMapKey, paramId]
     * @返回类型: void
     */
    public static void saveEsfTopNDataToRedis(List<String> redisKeyList,String tempMapKey,String paramId){

        Jedis jedis = CodisUtil.getClient();
        try{
            for (String baseKey : redisKeyList) {
                // 用于去重数据
                String tempEsfKey = "temp_esf_" + baseKey;
                // 保存最终的数据
                String finalEsfKey = "esf_" + baseKey;
                // 判断数据是否存在
                Boolean exists = jedis.hexists(tempEsfKey, tempMapKey);
                if (exists){
                    // 存在直接加1
                    jedis.hincrBy(tempEsfKey,tempMapKey,1);
                }else {
                    // 不存在,先创建辅助数据,用于去重
                    jedis.hset(tempEsfKey,tempMapKey,"1");
                    // 设置数据过期时间,因为这里是统计近7天某个主题UV的topN,所以设置有效时间8天,避免浪费内存
                    jedis.expire(tempEsfKey,8*60*60*24);
                    // UV 数据加1,这里使用 zset类型的存储,方便获取topN的数据,不用自己去单独排序,充分利用redis的特性
                    // 先判断是否有数据,没有新增,否则直接相加
                    Double zscore = jedis.zscore(finalEsfKey, paramId);
                    if (null != zscore && zscore > 0){
                        jedis.zincrby(finalEsfKey,1,paramId);
                    }else {
                        // 不存在的数据,直接加1
                        jedis.zadd(finalEsfKey,1,paramId);
                        // 设置过期时间
                        jedis.expire(finalEsfKey,8*60*60*24);
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(null != jedis){
                jedis.close();
            }
        }

    }

3、数据落地后对外提供使用:

        Jedis jedis = null;
        try {
            jedis = CodisUtil.getClient();
            Set<Tuple> tuples = jedis.zrevrangeWithScores(redisKey, 0, 4);
            for (Tuple tuple : tuples) {
                System.out.println("主题id:"+tuple.getElement()+";topN的值:"+tuple.getScore());
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (null != jedis){
                jedis.close();
            }
        }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、基于nginx+lua完成商品详情页访问流量实时上报kafka的开发 ==================================== 在nginx这一层,接收到访问请求的时候,就把请求的流量上报发送给kafka 这样的话,storm才能去消费kafka中的实时的访问日志,然后去进行缓存热数据统计 用得技术方案非常简单,从lua脚本直接创建一个kafka producer,发送数据到kafka ``` wget https://github.com/doujiang24/lua-resty-kafka/archive/master.zip yum install -y unzip unzip lua-resty-kafka-master.zip cp -rf /usr/local/lua-resty-kafka-master/lib/resty /usr/hello/lualib nginx -s reload local cjson = require("cjson") local producer = require("resty.kafka.producer") local broker_list = { { host = "192.168.31.187", port = 9092 }, { host = "192.168.31.19", port = 9092 }, { host = "192.168.31.227", port = 9092 } } local log_json = {} log_json["headers"] = ngx.req.get_headers() log_json["uri_args"] = ngx.req.get_uri_args() log_json["body"] = ngx.req.read_body() log_json["http_version"] = ngx.req.http_version() log_json["method"] =ngx.req.get_method() log_json["raw_reader"] = ngx.req.raw_header() log_json["body_data"] = ngx.req.get_body_data() local message = cjson.encode(log_json); local productId = ngx.req.get_uri_args()["productId"] local async_producer = producer:new(broker_list, { producer_type = "async" }) local ok, err = async_producer:send("access-log", productId, message) if not ok then ngx.log(ngx.ERR, "kafka send err:", err) return end ``` 两台机器上都这样做,才能统一上报流量到kafka ``` bin/kafka-topics.sh --zookeeper 192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181 --topic access-log --replication-factor 1 --partitions 1 --create bin/kafka-console-consumer.sh --zookeeper 192.168.31.187:2181,192.168.31.19:2181,192.168.31.227:2181 --topic access-log --from-beginning ``` (1)kafka在187上的节点死掉了,可能是虚拟机的问题,杀掉进程,重新启动一下 nohup bin/kafka-server-start.sh config/server.properties & (2)需要在nginx.conf中,http部分,加入resolver 8.8.8.8; (3)需要在kafka中加入advertised.host.name = 192.168.31.187,重启三个kafka进程 (4)需要启动eshop-cache缓存服务,因为nginx中的本地缓存可能不在了 二、基于storm+kafka完成商品访问次数实时统计拓扑的开发 ==============

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值