精华内容
下载资源
问答
  • 基于 hive 的日志数据统计实战 http://blog.csdn.net/sutine/article/details/5653137

    基于 hive 的日志数据统计实战


    http://blog.csdn.net/sutine/article/details/5653137

    展开全文
  • java版数据分析--上网日志流量统计

    千次阅读 2018-05-01 17:15:18
    在给的http.log日志文件中,是电信运营商记录用户上网访问某些网站行为的日志记录数据,一条数据中有多个字段用空格分隔。例如:"18611132889 http://v.baidu.com/tv 20 5000"是一条上网行为,第一个字段...

    在给的http.log日志文件中,是电信运营商记录用户上网访问某些网站行为的日志记录数据,一条数据中有多个字段用空格分隔。

    例如:"18611132889 http://v.baidu.com/tv 20 5000"是一条上网行为,第一个字段代表手机号码,第二个字段代表请求网站的URL,第三个字段代表请求发送的数据即上行流量(20字节),第四个字段代表服务器响应给用户的流量即下行流量(5000字节)。

    数据

     

    手机段规则

     

    需求:

    1.计算出用户上网流量总流量(上行+下行)最高的的网站Top3

    2.根据给的的手机号段归属地规则,计算出总流量最高的省份Top3

    3.根据给的的手机号段运营商规则,计算出总流量最高的运营商Top3

    步骤分析:

    1将手机号规则信息放在Map集合中,以手机号为key,手机数据实体为value

    2加载http日志数据,获取url和手机号数据(url需要简单清洗)

    3 处理url数据,统计流量

    4 根据http日志文件中的手机号匹配获取对应的区域运营商数据,进行统计

    知识点:

    集合 listmap存储数据特点

    IO 切割

    1.1. 创建两个实体bean来存储手机号规则数据和上网数据

    HttpBean  pojo

    private String phone ;//手机号

    private String url ;//请求的url

    private int upData ;//上行流量

    private int lowData ;//下行流量

    TelBean

    private String prefix ;

    private String phone ;

    private String province ;

    private String city ;

    private String isp ;

    private String postCode ;

    private String cityCode ;

    private String areaCode ;

    1.2. 读取手机号规则数据 将数据封装到Map

    /**

     * Tel放在map

     * @return

     */

    public static Map<String, TelBean> getTelMap() {

    Map<String, TelBean> map = new HashMap<>();

     

     

     

    try (BufferedReader bfr = new BufferedReader(new FileReader("d:/data/手机号段规则.txt"));) {

    String line = null;

    bfr.readLine();

    while ((line = bfr.readLine()) != null) {

    // System.out.println(line);

    String[] split = line.split("\\s");

    String prefix = split[0];

    String phone = split[1];//七位

    String province = split[2];

    String city = split[3];

    String isp = split[4];

    String postCode = split[5];

    String cityCode = split[6];

    String areaCode = split[7];

    TelBean telBean = new TelBean(prefix, phone, province, city, isp, postCode, cityCode, areaCode);

    map.put(phone, telBean); // key七位的手机号

    }

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    return map;

    }

     

    1.3. 将手机号规则数据存储在list

    /**

     * 返回Tellist数据

     * @return

     */

    public static List<TelBean> getTelList() {

    List<TelBean> list = new ArrayList<>();

    try (BufferedReader bfr = new BufferedReader(new FileReader("d:/data/手机号段规则.txt"));) {

    String line = null;

    bfr.readLine();

    while ((line = bfr.readLine()) != null) {

    // System.out.println(line);

    String[] split = line.split("\\s");

    String prefix = split[0];

    String phone = split[1];

    String province = split[2];

    String city = split[3];

    String isp = split[4];

    String postCode = split[5];

    String cityCode = split[6];

    String areaCode = split[7];

    TelBean telBean = new TelBean(prefix, phone, province, city, isp, postCode, cityCode, areaCode);

    list.add(telBean);

    }

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    return list;

    }

     

    由于List集合和Map集合存储数据的特点不同,此案例我们选择使用map集合

      List需要根据手机号获取其对应的区域需要遍历并匹配手机字段

     

    Map存储手机号规则数据,可将手机号作为keyTelBeanvalue数据,直接根据key来获取其对应的区域信息

     

    1.4. 统计url的访问流量

    /**

     * 统计URl结果

     * @return

     */

    public static Map<String,Integer> getUrlResult() {

    //统计各个url的访问量数据

    Map<String,Integer> urlMap = new HashMap<>();

    try (BufferedReader bfr = new BufferedReader(new FileReader("d:/data/http.log"));){

    String line = null ;

    while((line = bfr.readLine())!=null){

    //System.out.println(line);

    String[] split = line.split("\\s");

    String phone = split[0];

    String urlStr = split[1];

    String upDateStr = split[2];

    String lowDataStr = split[3];

    //处理url数据  清洗掉数据格式不正确的数据

    String[] split2 = urlStr.split("\\.");

    if(split2.length>=3){//如果url包含两个 点

    String url = split2[1];

    Integer sum = urlMap.getOrDefault(url, 0);

    sum += Integer.parseInt(upDateStr)+Integer.parseInt(lowDataStr);

    urlMap.put(url, sum);//结果数据

    }

    }

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    return urlMap;

    }

    1.5. 统计省份和运营商的访问流量统计

    static Map<String, TelBean> telMap ;

    static{

    telMap = TelAdmin.getTelMap();

    }

     

    public static void main(String[] args) {

    //存储省份结果

    Map<String,Integer> pMap = new HashMap<>();

    //存储运营商结果

    Map<String,Integer> ispMap = new HashMap<>();

    //存储统计url结果

    Map<String,Integer> urlMap = new HashMap<>();

    try (BufferedReader bfr = new BufferedReader(new FileReader("d:/data/http.log"));){

    String line = null ;

    while((line = bfr.readLine())!=null){

    //System.out.println(line);

    String[] split = line.split("\\s");

    String phone = split[0];

    String urlStr = split[1];

    String upDateStr = split[2];

    String lowDataStr = split[3];

    String tel = phone.substring(0, 7);

    TelBean telBean = telMap.get(tel);

    String province = telBean.getProvince();//省份

    Integer tatol1 = pMap.getOrDefault(province, 0);

    tatol1 +=Integer.parseInt(upDateStr)+Integer.parseInt(lowDataStr);

    pMap.put(province, tatol1);

    String isp = telBean.getIsp();//运营商

    Integer tatol2 = ispMap.getOrDefault(isp, 0);

    tatol2 +=Integer.parseInt(upDateStr)+Integer.parseInt(lowDataStr);

    ispMap.put(isp, tatol2);

    String[] split2 = urlStr.split("\\.");

    if(split2.length>=3){

    String url = split2[1];

    //System.out.println(url);

    Integer tatol = urlMap.getOrDefault(url, 0);

    tatol += Integer.parseInt(upDateStr)+Integer.parseInt(lowDataStr);

    urlMap.put(url, tatol);

    }

    }

    //对结果集map排序  获取想要的结果

    ispMap.entrySet();

     pMap.entrySet();

    urlMap.entrySet();

    } catch (Exception e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    1.6. map排序工具类

    public static ArrayList<Entry<String, Integer>> sort(Map<String,Integer> map){

    Set<Entry<String, Integer>> entrySet = map.entrySet();

    ArrayList<Entry<String, Integer>> list = new ArrayList<>(entrySet);

    Collections.sort(list,new Comparator<Entry<String, Integer>>() {

    @Override

    public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {

    return o2.getValue().compareTo(o1.getValue());

    }

    });

    return list;

    }

    展开全文
  • 日志统计

    千次阅读 2019-03-15 17:34:14
    标题:日志统计 小明维护着一个程序员论坛。现在他收集了一份"点赞"日志日志共有N行。其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞"。 现在小明想统计有哪些帖子...

    标题:日志统计

    小明维护着一个程序员论坛。现在他收集了一份"点赞"日志,日志共有N行。其中每一行的格式是:

    ts id  

    表示在ts时刻编号id的帖子收到一个"赞"。  

    现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K个赞,小明就认为这个帖子曾是"热帖"。  

    具体来说,如果存在某个时刻T满足该帖在[T, T+D)这段时间内(注意是左闭右开区间)收到不少于K个赞,该帖就曾是"热帖"。  

    给定日志,请你帮助小明统计出所有曾是"热帖"的帖子编号。  

    【输入格式】

    第一行包含三个整数N、D和K。  

    以下N行每行一条日志,包含两个整数ts和id。  

    对于50%的数据,1 <= K <= N <= 1000  

    对于100%的数据,1 <= K <= N <= 100000 0 <= ts <= 100000 0 <= id <= 100000  

    【输出格式】

    按从小到大的顺序输出热帖id。每个id一行。  

    【输入样例】

    7 10 2  

    0 1  

    0 10    

    10 10  

    10 1  

    9 1

    100 3  

    100 3  

    【输出样例】

    1  

    3  

    资源约定:

    峰值内存消耗(含虚拟机) < 256M

    CPU消耗  < 1000ms

    请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

    注意:

    main函数需要返回0;

    只使用ANSI C/ANSI C++ 标准;

    不要调用依赖于编译环境或操作系统的特殊函数。

    所有依赖的函数必须明确地在源文件中 #include <xxx>

    不能通过工程设置而省略常用头文件。

    提交程序时,注意选择所期望的语言类型和编译器类型。
     

    #include <stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<algorithm>
    #include<math.h> 
    using namespace std;
    int n,d,k;
    pair<int,int> idts[1000005];//这是一个能记录两个整型的类型pair 
    int judge(int a,int b){//尺取法判断 
    	int l=a,r=a,sum=0;
    	while(l<=r&&r<=b){
    		sum++;
    		if(sum>=k){
    			if(idts[r].second-idts[l].second<d) return 1;
    			else{
    				l++;sum--;
    			}
    		}
    		r++;
    	}
    	
    	return 0;
    }
    int main()
    {
    //	freopen("a.txt","r",stdin);
    	int ts,id;
    	scanf("%d %d %d",&n,&d,&k);
    	for(int i=0;i<n;i++){
    		scanf("%d %d",&ts,&id);
    		idts[i].first = id;
    		idts[i].second = ts;
    	}
    	sort(idts,idts+n);//按照id先,然后同id下ts排序排序 
    	int i=0;
    	while(i<n){
    		id = idts[i].first;
    		int begin = i,end;
    		while(id==idts[i].first && i<n){
    //			cout<<" "<<idts[i].second;
    			end = i;
    			i++;
    		}
    //		cout<<begin<<" "<<end<<endl;
    		if(judge(begin,end))//begin表示同id下的最小下标,end表示同id下最大下标 
    		printf("%d\n",idts[begin].first);
    		
    	}
        return 0;
    }

     

    展开全文
  • 日志统计到大数据分析

    万次阅读 2016-12-22 16:44:46
    2007年浙大研究生毕业后加入百度,从2008年开始从事数据方向,从零构建了百度的用户日志数据处理平台。2015年4月从百度离职,创建神策数据,帮助客户实现数据驱动。这篇文章讲述我在百度从零构建大数据平台方面的...

    作者:桑文锋,神策数据创始人&CEO,前百度大数据部技术经理。2007年浙大研究生毕业后加入百度,从2008年开始从事数据方向,从零构建了百度的用户日志大数据处理平台。2015年4月从百度离职,创建神策数据,帮助客户实现数据驱动。目前,面向互联网创业公司的产品神策分析的客户包括爱鲜蜂、多盟、AcFun、秒拍等。

    2008年底,我开始在百度负责一个日志统计的小团队,开发了一套基于Hadoop的日志统计平台,结果一年半的时间统一了全百度的日志统计工作。之后一直围绕数据这一方向,覆盖数据的采集、传输、建模存储、查询分析、数据可视化等,打造了全百度的用户数据仓库(User Data Warehouse),并推动全公司核心业务线的日志源结构化(Protocol Buffer)。这篇文章讲述我在百度从零构建大数据平台方面的经历。

    洪荒年代

    首先,我们回到2008年。那个时候,我是属于百度搜索新产品部的,像知道、贴吧、百科等,都属于这个部门的产品。部门里有个小团队叫Nslog,一共四个人,其中两个是实习生,所负责的工作就是部门内的各种需求统计。

    统计的方式是这样的,各个产品线的业务人员按照需求文档的格式要求,填写统计需求,提交到需求管理平台上,Nslog的团队负责人(开始不是我负责)每周末,将需求分别分配给团队的几个成员。每个成员拿到需求列表之后,就挨着做。需求的实现,一般都是写 Perl 脚本,那个时候 Python 还没流行起来。因为统计需求比较类似,一般都是拿一个已有的脚本复制一份,修改一下,测试逻辑,测试大数据量下的准确性,然后部署到线上去。一共有20台机器跑统计脚本,每台机器上都用Crontab配置天级的例行任务。每个统计脚本的逻辑大概是这样的:通过Wget从数据源服务器上抓取按小时切割的日志文件,完成后,跑统计逻辑,将生成的结果组织成HTML表格,邮件发送给相应的团队。如下图所示:

    (图1 使用单机脚本跑统计)

    这种模式有以下几个问题:

    (1)需求响应周期长:从拿到需求,要和需求提出者确认需求细节,找一个类似的脚本修改,测试逻辑正确性,测试数据正确性,安排运维同学部署上线,平均每个需求要2天时间。这里还没算需求的等待时间,这可能要等一两周。 
    (2)运维成本高:20台统计服务器,每台机器通过Crontab管理了几十个脚本。这些脚本之间,可能还存在依赖关系,比如凌晨4点跑的一个脚本B,依赖于凌晨2点启动的某个脚本A。如果脚本A挂了,脚本B还是会正常的启动。恢复任务非常麻烦,真是牵一发而动全身。运维同学经常抱怨就没有哪一天能睡好觉的。 
    (3)运行速度慢:因为每个脚本只能单机运行,对于像知道、贴吧这样的大流量业务线,每天原始日志就有好几百G,光跑个排序就得好几个小时。特别是像贴吧被人爆吧,数据量一下子就会增加很多,统计结果跑不出来。如果分成每台机器跑一部分,维护代价非常大。 
    (4)职业发展瓶颈:那个时候还没有大数据的概念,大家对数据的价值也没现在这么认可,甚至连招聘面试时,也是把能力一般的分配到统计团队。而写脚本满足需求这样的工作是很枯燥的,对一个新人,写上三个月会觉得能学到不少东西,写六个月,就开始反感了,写一年,就坚决要求转岗或走人了。

    当时我们的技术经理(同时管理了知道、百科、Nslog 三个团队)就觉得要做一套系统首要解决运维成本高的问题。但已有团队的人员光满足需求都忙不过来了,就从百科团队借调了两个人(不包括我)。那时候的我刚从百度知道转到百科团队,正想在百科团队大干一场。借调去的两个人其中一个是校招新人,我的项目经理就安排我也参与到项目中,培养新人的成长。于是我们三个人开始梳理需求和考虑设计方案。

    盘古开天地一

    设计一套日志统计平台的需求来源主要是Nslog的研发和运维同学,整理了好几十条,并出了一个基本的方案。我当时觉得实现一个提升运维管理的系统不难,难的是怎么是好用的?我很关心怎么提升需求处理的效率问题。这个时候其中一个人又被调到了一个基础库团队。也就是做这件事的就只剩我和校招新人了。而我们两个都还没做过需求处理,也不知道那几百个脚本里面都写的什么玩意儿。我说咱俩每人至少要看三个脚本,再抽查一些,看看这些脚本都有什么规律没有。我研究了之后,发现还是有些规律的。

    我发现常见的统计有这么三类:

    (1)计数统计:那个时代是流量时代,许多统计就是算PV(Page View)。一般是在 Apache Web Server日志中,去用正则表达式匹配满足某些条件的记录,做计数。 
    (2)去重统计:比如独立 IP 数,独立用户数等。 
    (3)Top N统计:比如昨天检索量最大的100个Query是什么。

    我就问一直做统计的一位同学,这三类能不能占到所有统计需求的80%,他想了一下说有的。于是我就说咱们只要设计的系统,能够将这部分的需求处理工作量降下来,我们的系统就是成功的。这个时候技术经理又从其他团队借调了一个前端同学过来支援几周。我和校招新人都不会前端开发,这事儿没专业的人来搞不定。在接下来的两周时间,我就和前端同学研究怎么设计这部分的抽象。前端同学先提了一个方案,类似于 Dreamweaver中的页面HTML编辑界面,点选一个元素,可以进行修改配置。我觉得这种方案,还没直接写脚本效率高呢。

    我从awk脚本语言获取了灵感。在awk语言中,都是awk condition { action } 这种模式,就是condition定义了满足的限制条件,action是执行的操作。比如:

    awk ‘$6 == "Nov" { sum += $5 } END { print sum }’ ./test.txt

    就是把test.txt中,满足第6列等于 “Nov” 的记录,计算第5列的求和。

    对于常见的那三类统计需求,都是一种统计类型,加上一堆限制条件。为了降低限制条件的难度,我让所有的条件之间只支持AND操作,不支持OR操作。我们知道AND和 NOT完全可以表示出来OR。

    设计出来的效果是这样的:

    (图2 简单编辑界面)

    上面是一个去重统计的例子,我选择一个日志源,点击“去重统计”按钮,生成一个模版,填写限制条件。一个统计任务就生成了。这里没有显示出来的是,每个日志源,都有一个对应的agent函数,所做的事是一段解析程序,将原始日志解析成若干个变量,如图中的去重字段部分,类似“_UserId”,这样在统计模板中就可以直接使用了。这样做了之后,可以让一个统计任务的开发工作量,降低到5分钟。

    还有一个问题是计算性能问题。

    盘古开天地二

    当时Hadoop刚推出,还只是测试版。对于它能解决多少问题,我们心里是没底的。在百度内部已经有少量的需求在尝试使用,手工写 MapReduce 代码的方式。我也尝试写了一个,还是比较容易的,但有一定的学习代价。系统部有一个团队,在负责Hadoop 的维护。为了保险,我把底层计算接口设计成两套,同样的代码,既可以提交到Hadoop,又可以提交到单机。在单机上用脚本串起来,模拟在集群上的运行。Hadoop本身支持将任务分割为Mapper和Reducer两个阶段,我又增加了一个Computer阶段,作用是将Reducer的结果(一般是统计数值)拿到执行机(分布式提交任务的节点),并将其插入到数据库。我当时的想法是如果Hadoop不靠谱,我就把这20台单机,组成一个小集群,管理提交的任务。当然,这样的话就实现不了单个任务的分布式化了。

    整个架构图是这样的:

    (图3 初版日志统计平台架构图)

    其中Code Engine和CWrapper是我设计和实现的,Scheduler和数据库表设计是校招新人实现的,Web UI是后来加入的实习生花了一周时间找了个网上的模板改的。日志的上传是运维同学开发的。为了说服运维同学完成部分开发工作,承诺让其将所有的数据上传之后,再更新数据库里的数据源就绪状态。

    在这个系统实现中,我们把PHP用到了极致,Web UI是PHP的,后端的几个模块是 PHP的,就连生成的 MapReduce代码,也是PHP的。有人可能会对PHP的运算性能有疑问,当时负责Hadoop维护的同学为了推动更多的人使用,承诺我们100多台机器随便用,不用考虑性能问题,缺机器了他们直接申请加,我们就没这方面的考虑。PHP 的开发效率还是很高的,我的 Code Engine 实现任务配置到 MapReduce 代码的编译,最初的版本只花了我2个小时,140行代码。

    就这样,一个伟大的系统经过两三个月的时间拼凑完成了。其实到快发布,还没有名字。有一天经理问我叫什么,我说就叫 Log Statistics Platform的前三个字母LSP,于是就有了名字(之后我为了方便记忆,让大家把平台叫做 Log 平台)。

    平台带来了几点好处:

    (1)需求响应周期大大缩短:因为对常用的三类统计做了很好的抽象,即使产品同学都能直接配置统计任务,开发周期从2天时间降低到5分钟。并且统计需求的处理,完全交还给了各个业务方,没有了需求等待时间。 
    (2)运维成本大大降低:由统一的系统进行任务的管理,具有依赖关系的管理,大大降低了出错带来的恢复成本。 
    (3)运行速度飞快:我现在仿佛还能回忆起从平台上提交第一个任务时的感觉,以前几个小时才能跑完的任务,只需要几分钟就跑完了。我之前担心的 Hadoop 不能覆盖所有统计需求的问题,也不存在。 
    (4)组员积极性变高,终于在干一件有点技术含量的事了。

    盘古开天地三

    平台在2009年4月正式发布后,各个团队的需求铺天盖地而来,日志源的中转上传很快就成了瓶颈。都是所有的日志源完成上传后,才开始统计计算,这样上传期间的几个小时时间就白白浪费掉了。我们首先将日志上传改成每份完成后单独打就绪标记。后来有次和 Hadoop 团队的同学沟通,我就提起能不能每个 Mapper 作为一个日志抓取的任务,这样可以让100多台机器同时抓数据,他们说没问题,已经有团队这么干。于是我们很快上线了新版本,实现分布式的抓取。

    架构改成了这样:

    (图4 分布式抓取架构)

    这时候的产品,已经是一个比较完整的产品了,我开始在公司范围内推广。本来公司里有十几个类似我们的统计团队,我就是要说服他们把任务迁移到我们平台。记得很深刻的一次是和网页搜索部的统计团队沟通,他们看了演示之后很震惊,说本来他们只是在设想这种系统的可能性,没想到你们已经做出来了。当时我们又入职了一位同学专门负责响应需求,有一天,业务部门的同学反馈说不能加他好友了(我们用的是百度自己的聊天软件 Baidu Hi),我们就找 Hi 团队的同事咨询,他们说这位同学到了好友上限2000人,之前还没遇到过这种情况。他们的解决方案是修改人数配置,重启整个 Baidu Hi 服务。

    在整个推广的过程中,我就像拿着一款先进设备,去拯救那些水深火热的人们。我们一边推广,一边完善整个平台。

    从最开始平台是为统计而生,但我渐渐的发现,统计只是一类需求,其他Hadoop任务,也可以通过我们这个平台管理起来。我就想将Log平台发展为Hadoop的壳,所有提交给Hadoop的任务,都能通过Log平台管理起来。Log平台演化成一个通用计算平台。

    我前面提到通过三类常见统计的抽象,来解决80%的问题。但当这80%需求解决之后,你会发现又有新的80%的需求冒出来。如果让用户直接写MapReduce任务提交,这个代价太大了。平台开始上线时,提交任务就支持两种模式。一种是简单编辑,就是前面的三类抽象(后来加了更多的类别)。一种就是复杂编辑,直接贴MapReduce代码。对于后者,如果能抽象一个更好用的计算框架,将MapReduce隐藏起来,显然就又可以提升开发效率了。

    我就安排一个工程师(目前是我的合伙人之一)出一个方案,只用了一周时间,就设计出来原型了。下面是个例子(我们叫它 DQuery):

    (图5 DQuery 代码样例)

    对于一个输入,我们可以去选择某些字段,进行分组,每组在计数,然后输出到一个文件。这样就实现了一个统计任务。这种链式的处理方式,在现代已经很普遍了,特别是 Spark 里都是采用的类似表示方法。我们在2009底做了这个事情,在2011年公司号召多提交专利时,提交了发明专利。今年3月初时,专利刚被审核通过。这种将数据流式的进行变换的思想,已经见诸于各大分布式计算系统。

    在给出 DQuery 原型后,我觉得团队太弱小了,只能有一个全职参与这件事。于是找基础库团队的同学寻求支持。他们最开始提出何不实现一个 Google Sawzall,但我觉得太底层了。最终说服对方安排一位工程师参与进来。结果就是他们两个人花了2个半月,就把这个语言开发出来了。

    可能你会问为什么当时不选择使用 Hive?事实上,那个时候 Hive 的工程师也来公司交流和推广了。但有两个需求不好满足: 
    (1)任务合并:对于同一个数据源,可能有几百个统计任务。这种统计任务可能都很简单,但是都要将数据源读取一遍,也就是一个高 IO 低 CPU 的任务。我们当时想直接读取一遍,然后将多个任务同时计算,这样效率会高很多。这在 Hive 上是不支持的。 
    (2)用户行为分析:我当时比较乐观,觉得我一年解决统计问题,第二年解决分析问题,第三年解决挖掘问题。事实上到现在分析问题也没解决彻底。我们知道 Hive 是基于 SQL 的,而 SQL 是上下文无关的。也就是说你取出的一批数据,有前后关系的话,是很难操作的。我需要在语言上支持。而在 DQuery 语言中,我们设计了一个方法叫 process,可以嵌入用户的逻辑,非常灵活。这里要说的是 DQuery 是一个基于 PHP 语言的框架,这样 DQuery 表达不了的,都可以写原始 PHP 代码。

    就这样到2010年底的时候,实现了全公司日志统计全部统一到 Log 平台。这是我在百度八年,干的最有成就感的一件事情。 
    秦天下

    转眼到了2011年初,那个时候团队已经合并到了网页搜索部的相关性部门,我感觉这不利于发展。我的想法是要把团队面向全公司服务,甚至成为像 NLP(自然语言处理)部门在厂长心中的地位。但网页相关性部门的上司觉得先服务好本部门就够了。我和基础架构部的一个经理(最早在百度负责维护和开发 Hadoop 团队的负责人,在他完成了 Hadoop 在全百度的推广之后,改为负责一个分布式存储团队了)商量了一下,觉得两个团队合并,成立一个专门的数据团队,是一件更有意义的事。两人一拍即合。基础架构部的老大又从 Google 挖来了一位专家做我们团队的负责人,他之前在 Yahoo 做了7年,Google 做了5年,一直在做数据仓库,绝对的资深专家,我很崇拜的人。

    记得在2011年的7月1日,团队开了个All Hands大会,公司 VP 在讲话中说:在中国是 D 说了算,在百度也是 D 说了算,后一个 D 是指 Data 。说起来在百度这八年,百度文化有29条,我第二喜欢的就是“用数据说话”,数据虽然有欺骗性,但总的来说有数据要比没有数据好,它不带有感情,冷静客观。就这样,我们 DataTeam 成立了,或者叫 DreamTeam。团队的一线人员一共二十来个,超过一半是我之前的下属。

    有新总监的领导,我们的思路完全被打开了一圈。但在最开始,我们的思路依旧有些混乱,之前的产品还要维护,想做的新东西很多,我们似乎没有一个中心。眼看到了国庆,有一天我问新总监他觉得什么最重要,如果只挑一件事情的话,他说是 UDW(User Data Warehouse,意为用户数据仓库)。我说那咱们核心成员就用来做这个项目。于是我迅速将 Log 的核心成员,抽调到了这一项目,在之后的三年里,我的主要精力可以说都是围绕它展开的。

    在新总监来到百度之后,很快发现了我们的数据源真叫一个混乱。公司有上百个业务线,每个业务线的数据格式都是不同的。如果你要基于所有的数据源做一个业务,比如个性化推荐,那么需要和所有的业务线沟通数据格式,并维护这条飞线。相比之下,在 Google 数据源都是被规范管理的,使用 Protocol Buffer 来规范数据格式。新总监认为我们要先把数据源给统一起来,形成一个好的数据基础,后续的数据分析完全依赖于它。

    对于这种思路,我是有疑虑的。在2009年的时候,我就做了一个叫麦哲伦的用户行为查询平台,通过输入一个 ID,返回用户的行为记录,主要包括知道,百科,贴吧之类的产品。当时的做法是我把每个产品线的用户访问行为,比如在百度知道提问,用一个 Action ID 来标记,这个行为有一系列属性。对于有些属性,我还和业务线建立了专门的接口,用于获取这些属性的具体内容。比如通过问题的 ID,获取到问题的标题,以保证行为记录的可读性。这个系统是很快建立起来了,但被使用的频率非常低。花很大精力整理的数据,似乎一时半会儿看不到多大价值。还有个问题是业务线的数据格式变更,我的数据处理逻辑都要更新,很难维护。所以这种思路被重新提出时,我最顾虑的是做出来之后有什么用,在应用点不明确的时候,我们是不是该做这件事。但新总监在公司层面很快推动达成了一致,总之是公司支持做这件事情。执行从来不是我的问题,既然都确定要做了,我很快就带着团队做起来。最开始选择最核心的八条业务线,在2012年的 Q1 季度末,正式对公司内部发布了。

    UDW 做了一件事情,将全公司的每个业务线的每一种用户行为,定义为一种 Event,这个 Event 包括一系列的属性,核心的是 UserID,Event Type,事件相关的其他属性。这样,一个用户在百度的任意行为就统一到了一张表上。再有人想做数据分析,就可以直接用干净统一的基础数据了。

    从数据角度来看,是一个金字塔:

    (图6 数据金字塔)

    最底层是上百条业务线的文本日志,通过 LogFormat 转成 Protocol Buffer 格式。在此基础上,构建 UDW。在 UDW 基础之上,我们构建围绕各种主题的数据,形成 DataMart。比如基于 Query 的基础数据。再进一步汇聚,就可以用于 BI 的 Insight。

    这里我总结一下 UDW 思路的优缺点。优点是为上层应用提供了一套统一干净的基础数据,上层的使用变得非常简单。一个广告团队,仅仅是将数据源切换到 UDW,就提升了接近20%的收入。更何况以前在做个需要多个业务线数据源的应用,只需要和我们 UDW 打交道,这减少了多大的工作量和沟通成本。

    不好的地方是源头的数据并没有变更,我们中间是通过 ETL 过程将数据接入到 UDW 的,而这个过程工作复杂难以维护,具有很长的滞后性。并且因为多了一轮计算,实效性也降低了。一些业务线开始抱怨,对 UDW 产生了严重依赖,特别是相对比较独立的业务线,做这件事完全没什么好处,还不如根据原始数据来计算。

    在这之后,我又带着团队完成了核心数据源的日志 Protocol Buffer 改造,并构建了新的传输、查询、调度系统。在2012年初老大给我讲 Google 那边能够打了日志马上就可以分析,我都觉得很不可思议,那时候百度的延迟至少是小时级的。可经过两年多的努力,我们也达到了这一点。以上是我的经历分享,希望能够给读者启发,少走一些弯路。

    来源:CSDN。

    链接:http://wwwbuild.net/CSDNnews/215881.html?from=account

    展开全文
  • 根据访客日志统计访客数据

    千次阅读 2016-05-12 13:24:16
    每一个网站都会根据访客日志统计访客数据,比如UV。UV能够回答一个关键的市场营销问题:“到底有多少人(潜在客户)看到了你发布的信息(即网站)。 下面根据题目给出的某购物网站访问日志统计当天该网站UV。日志...
  • 统计业务日志中关键字的数量,并在...本教程的目的是通过一个具体案例介绍如何对存储在日志服务产品中的数据进行关键字统计和报警。参照本教程的介绍,您可以快速走通日志的关键字统计、查询图表可视化和设置报警流程。
  • 基于Hive的日志数据统计实战

    千次阅读 2011-05-03 16:32:00
    一、Hive简介 Hive 是一个基于 hadoop 的开源数据仓库工具,用于存储和处理海量结构化数据。 它把海量数据存储于 hadoop 文件系统,而不是数据库,但提供了一套类数据库的数据存储和处理机制,并采用 ...
  • 基于hive的日志数据统计实战

    万次阅读 2010-06-07 15:35:00
    Hive是一个可扩展性极强的数据仓库工具,借助于hadoop分布式存储计算平台和hive对SQL语句的理解能力,我们所要做的大部分工作就是输入和输出数据的适配,恰恰这两部分IO格式是千变万化的,我们只需要定制我们自己的...
  • Java实现蓝桥杯日志统计

    万次阅读 多人点赞 2020-03-02 16:52:17
    标题:日志统计 小明维护着一个程序员论坛。现在他收集了一份"点赞"日志日志共有N行。其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞"。 现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾...
  • 我们可以使用下面的命令行,统计服务器返回的状态码,发现系统可能存在的问题。 awk '{print $9}' access.log | sort | uniq -c | sort 正常情况下,状态码 200 或 30x 应该是出现次数最多的。40x 一般表示...
  • 数据收集---web访问日志收集与统计

    千次阅读 2015-12-25 17:33:01
    话说web访问日志,很多同学对百度统计,谷歌统计(google analytics)很熟悉,就是加点js代码埋点,然后很方便可以从百度等获得网站的访问情况统计。这种方式的确是很方便,自己可以不用管日志数据,对系统的影响也...
  • Apache日志统计

    千次阅读 2015-01-03 21:29:20
    Apache日志统计举例 加些来了解一下如何统计Apache的访问日志,一般可以用tail命令来实时查看日志文件变化,但是各种的应用系统中的日志会非常复杂,一堆长度超过你浏览极限的日志出现在你眼前时,你会觉得非常无奈...
  • 在上一篇《网站数据统计分析之一:日志收集原理及其实现》中,咱们详细的介绍了整个日志采集的原理与流程。但是不是这样在真实的业务环境中就万事大吉了呢?事实往往并非如此。比如针对前端采集日志,业务的同学经常...
  • 日志统计(蓝桥杯)

    千次阅读 2019-02-25 14:50:07
    日志日志共有N行。其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞"。 现在小明想统计有哪些帖子曾经是"热帖"。如果一个帖子曾在任意一个长度为D的时间段内收到不少于K...
  • 网站数据统计分析工具是网站站长和运营人员经常使用的一种工具,比较常用的有谷歌分析、百度统计 和 腾讯分析等等。所有这些统计分析工具的第一步都是网站访问数据的收集。目前主流的数据收集方式基本都是基于...
  • 1、需求分析 日期 uv pv 登录人数 游客人数 平均访问时长 二跳率 独立ip数 如何获取: 登录:userid有值,会员,有账号登录 游客:userid无值,非登录人员(都有身份认证的唯一id) 平均访问时...独立ip数:统计i...
  • 一:10亿条数据排序 思路:数据量比较大,普通比较会占用很多的内存,可以采用其他方法,构造一个字节数组 每个字节的值代表连续八个整形数据的值是否存在,即使包括最大的整数值,大概内存512m 源码如下 import ...
  • python 日志分析统计脚本

    千次阅读 2012-10-19 15:58:57
    python 日志分析统计脚本 脚本类似shell的tail功能,用来统计每分钟的4xx、5xx的状态码数量,统计php执行时间小于1秒、1-5秒、5秒以上的数量,和每秒的并发请求。将结果放到/tmp目录下, 也可以用cacti将结果画图...
  • 问题:要求sparksql统计json日志条数存入mysql数据库。 环境:spark1.6.2,hadoop2.7.3,mariadb10.1.4,centos7 数据处理环境:spark-shell 交互环境 数据量:100以内的测试json数据集。 存储位置:HDFS文件系统。...
  • 电量统计日志分析

    千次阅读 2018-01-30 23:55:04
    Batterystats日志分析概述 由于项目组的原因,慢慢的接触了一些Android系统的“快省稳”知识,最近陆续学习了一些关于功耗的知识,而Batterystats日志是搞功耗的日常工作之一,搞功耗人员,每天都要从用户反馈和...
  • 友盟错误日志统计没有数据的问题

    千次阅读 2017-05-15 15:27:30
    建议更新到新版本 (5)错误数据是下次启动应用时发送本次的错误数据(安卓需要间隔30秒以上算作新的启动) (6)需要在错误列表中编辑添加下应用的版本,不添加版本是看不到该版本的错误数据 (7)打印debug日志看...
  • shell统计日志信息

    千次阅读 2017-07-01 16:02:11
    shell统计日志信息一般应用中都会使用log4j记录日志信息,并每天生成一个日志文件,每个文件以当天的日期结尾。如何统计并分析这些日志信息?最简单的,使用shell脚本进行统计分析:下面的脚本就将最近一周的日志...
  • nginx简单的日志shell分析统计脚本

    千次阅读 2018-01-31 16:32:57
    简单的写了一个shell脚本,获取统计其中的参数。可能这个脚本需要优化的地方很多,只写了几点功能,先贴上,思路梳理 nginx日志参数简单介绍下 remote_addr:远端地址(客户端地址) time_local:日志记录...
  • 为了从访问日志中挖掘出更多价值,日志服务提供了一个docker镜像,用于实时统计和展示网站访问的一系列指标,例如PV,UV,延时,地理,状态码,爬虫,网络流量等指标。 指标 PV 分别以5分钟、1小时、1天为统计周期...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 252,011
精华内容 100,804
关键字:

日志数据统计500网