访客路径分析-Druid实践

一、背景

访客论分析是常见数据分析的一种,通过如上图(Google Analytics)以比较直观的方式展现用户达到网站后各条访问路径的流失情况,帮助网站优化减少流失率。

访客路径分析有如下几个关键点:

  • 用户访问的路径通常有多级,默认展开包含着陆页在内的5级路径,支持往后每点击一次展开一级路径(最高支持到10级,再往后意义不大)。
  • 每级只展示top 5访问数的网页,每级路径网页之间连接线表示跳转情况。
  • 指标包含top 5网页的会话数、流失数和剩余网页的会话数。

通过上述分析,要实现访客路径分析需要完成如下几项工作:

  1. 计算每一级所有网页的会话总数。
  2. 计算每一级会话数top 5的网页。
  3. 计算每一级两两网页之间的跳转访问数。

本文提出一种基于druid的实现方案,将上述3个查询转化为druid中的Timeseries(求总数)、TopN(求前5)、GroupBy(求两两关联)查询。

二、技术方案

数据清洗(ETL)
将用户pv流水根据,聚合成一个session会话。session会话内用户的访问流水按时间排序,取前11个分别放于维度landing_page ~ path10,ETL处理后的数据表格示例如下:

host landing_page path1 path2 ... path10
www.xxx.com /index.html /a /b ... /e
www.xxx.com /product.html /c /d ... null

数据入Druid供查询,schema设计如下

{
  "type" : "index_hadoop",
  "spec" : {
    "ioConfig" : {
      "type" : "hadoop",
      "inputSpec" : {
        "type" : "static",
        "paths" : ""
      }
    },
    "dataSchema" : {
      "dataSource" : "",
      "granularitySpec" : {
        "type" : "uniform",
        "segmentGranularity" : {"type":"period","period":"P1D","timeZone":"Asia/Shanghai"},
        "queryGranularity" : {"type":"period","period":"P1D","timeZone":"Asia/Shanghai"},
        "intervals" : []
      },
      "parser" : {
        "type" : "string",
        "parseSpec" : {
          "format" : "json",
          "dimensionsSpec" : {
            "dimensions": [
              "host",
              "landing_page",
              "path1",
               ...
              "path10"
            ]
          },
          "timestampSpec" : {
            "format" : "auto",
            "column" : "time"
          }
        }
      },
      "metricsSpec": [
        {
          "name": "count",
          "type": "count"
        }
      ]
    },
    "tuningConfig" : {
      "type" : "hadoop",
      "partitionsSpec" : {
        "type" : "hashed",
        "targetPartitionSize" : 5000000
      },
      "indexSpec" : {
        "bitmap" : { "type" : "roaring"},
        "dimensionCompression":"LZ4",
        "metricCompression" : "LZ4",
        "longEncoding" : "auto"
      }
    }
  }
}

三、具体实践

查询语句示例

计算每一级所有网页的会话总数(默认展示前5级),过滤掉为null的情况(用户只访问到上一级就跳出)。
{
  "queryType": "timeseries",
  "dataSource": "visit_path_analysis",
  "granularity": "all",
  "filter": {
    "type": "and",
    "fields": [{"type": "selector", "dimension": "host", "value": "www.xxx.com"}]
  },
  "aggregations": [
    { 
      "type": "filtered",
      "filter": { 
        "type": "not", 
        "field": { "type": "selector", "dimension": "landing_page", "value": null }
      },
      "aggregator": { "type": "longSum", "name": "count0", "fieldName": "count" }
    },
    { 
      "type": "filtered",
      "filter": {
        "type": "not", 
        "field": { "type": "selector", "dimension": "path1", "value": null }
      },
      "aggregator": { "type": "longSum", "name": "count1", "fieldName": "count" }
    },
    {
      "type": "filtered",
      "filter": {
        "type": "not", 
        "field": { "type": "selector", "dimension": "path2", "value": null }
      },
      "aggregator": { "type": "longSum", "name": "count2", "fieldName": "count" }
    },
    { 
      "type": "filtered",
      "filter": { 
        "type": "not", 
        "field": { "type": "selector", "dimension": "path3", "value": null }
      },
      "aggregator": { "type": "longSum", "name": "count3", "fieldName": "count" }
    },
    { 
      "type": "filtered",
      "filter": { 
        "type": "not", 
        "field": { "type": "selector", "dimension": "path4", "value": null }
      },
      "aggregator": { "type": "longSum", "name": "count4", "fieldName": "count" }
    }
  ],
  "intervals": []
}
计算每一级会话数top5的网页,过滤掉为null的情况(用户只访问到上一级就跳出)。
{
  "queryType": "topN",
  "dataSource": "visit_path_analysis",
  "granularity": "all",
  "dimension": "landing_page",
  "filter": {
    "type": "and",
    "fields": [
      {"type": "selector", "dimension": "host", "value": "www.xxx.com"},
      {
        "type": "not", 
        "field": { "type": "selector", "dimension": "landing_page", "value": null }
      }
    ]
  },
  "threshold": 5,
  "metric": {
    "type": "numeric",
    "metric": "count"
  },
  "aggregations": [{ "type": "longSum", "name": "count", "fieldName": "count" }],
  "intervals": []
}
计算每一级两两网页之间的跳转访问数,后一级的null用来计算流水数。
{
  "queryType": "groupBy",
  "dataSource": "visit_path_analysis",
  "granularity": "all",
  "dimensions": ["landing_page", "path1"],
  "filter": {
    "type": "and",
    "fields": [
      {"type": "selector", "dimension": "host", "value": "www.xxx.com"},
      {
        "type": "in",
        "dimension": "landing_page",
        "values": ["/a", "/b", "/c", "/d", "e"]
      },
      {
        "type": "in",
        "dimension": "path1",
        "values": ["/f", "/g", "/h", "/i", "/j", null]
      }
    ]
  },
  "aggregations": [{ "type": "longSum", "name": "count", "fieldName": "count" }],
  "intervals": []
}

四、总结分析

本文提出基于Druid来做访客路径分析的方案需由多个请求来完成。

  • 计算每一级所有网页的会话总数和计算每一级会话数top5的网页,在默认展示的时候可以先并行向druid发起请求。获取每级总会话数后再减去top5的会话数就是剩余其他网页的会话数。

  • 当得到每一级top5的路径后,只需要相邻两级路径做GroupBy查询即可获得转化数与流水数。

  • 当需要展示往后一级路径流转时,只需要基于当前最后一级的top5与下一级别top5做GroupBy计算即可。

  • 从数据分布来看,大部分流水集中在前几步,往后有数据级的差距。

  • 该方案最大挑战来着对Druid的并发请求,一个页面展示会扩大为多个Druid并发语句请求。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容