有序漏斗分析-Druid實踐

一、背景

漏斗分析是常見數(shù)據(jù)分析的一種,通過分析用戶在網(wǎng)站的行為,幫助運營人員分析一個多步驟過程中每一步的轉(zhuǎn)化與流失情況矮湘。比如定義一次電商活動(指定時間范圍比如最長30天)中用戶行為:訪問網(wǎng)站 -> 到達商品推薦頁 → 查看商品 → 生成訂單,統(tǒng)計用戶從訪問網(wǎng)站到下訂單完成轉(zhuǎn)化的數(shù)據(jù)就自然地形成了一個漏斗口糕。

通過上述描述得出幾個關(guān)鍵詞:

  • 用戶行為有序分析
  • 有轉(zhuǎn)化時間范圍(30天)
  • 用戶訪問數(shù)(會話數(shù))和用戶數(shù)(去重后的用戶基數(shù))

同時作為分析產(chǎn)品的話缅阳,挑戰(zhàn)點就是如何能夠基于用戶自定義先后訪問順序的情況下秒級分析出各層漏斗的情況。

本文提出一種基于Druid來實現(xiàn)的方案景描,該方案具有滿足需求的前提下實現(xiàn)成本小的優(yōu)點十办。

二、技術(shù)方案

有序漏斗分析問題超棺,本質(zhì)上為了解決在海量數(shù)據(jù)上根據(jù)自定義條件做搜索匹配的問題向族,那么思路的方向如何設(shè)計合理的數(shù)據(jù)存儲結(jié)構(gòu)和更有的匹配查詢方式。

做OLAP數(shù)據(jù)分析思路有兩類

  1. 基于明細統(tǒng)計查詢的方案:滿足查詢靈活性棠绘,但是大數(shù)據(jù)量下聚合統(tǒng)計分析類查詢性能不佳件相。
  2. 預(yù)聚合方案:滿足查詢性能要求,但是查詢不靈活氧苍、業(yè)務(wù)需要開發(fā)聚合數(shù)據(jù)邏輯夜矗,方案復(fù)雜(ETL層較重)。

基于Druid的方案:

  • 兼顧查詢靈活性與性能让虐、較少的開發(fā)成本紊撕,維度(查詢時組合) + 聚合指標(提前指定)。
  • 分布式架構(gòu)(高可用赡突、伸縮性)逛揩,自動rollup預(yù)聚合(業(yè)務(wù)開發(fā)簡單、只需導(dǎo)入原始記錄)+ 高壓縮比 + bitmap倒排索引麸俘。

分析用戶的行為,首先是需要把同一個用戶(user_id)的所有行為整理在一起惧笛,并且考慮到有訪問量的指標从媚,那么還需要基于網(wǎng)頁session會話(session_id)做數(shù)據(jù)聚合。

第一步:數(shù)據(jù)清洗(ETL)

根據(jù)會話ID按訪問時間把所有網(wǎng)頁數(shù)據(jù)聚合在一起患整,數(shù)據(jù)表如下:

host path_list session_time session_id user_id
www.123.com /1 /2 /3 1525243296 session_id_xxx1 user_id_xx1
www.abc.com /a /b /c /d 1525244296 session_id_xxx2 user_id_xx2

其中的關(guān)鍵是把所有頁面的path拼接在一起用空格分割拜效,目的是為了做漏斗匹配。這里可能大家會有疑問假如量很大怎么辦各谚?這里有兩個處理:1. 相鄰的兩個路徑若是相同則合并比如用戶同一個頁面刷新上報了兩次/1 /1那么在ETL的時候這里合并為一個/1紧憾;2. 一個session的時長是30分鐘,若是極端情況下一個用戶每秒都是訪問合1800秒昌渤,按平均一個路徑100byte來算也才180kb左右的大小赴穗。

第二步:清洗后的數(shù)據(jù)入Druid供查詢

原始入druid的數(shù)據(jù)就是上述一行session數(shù)據(jù),其中session_time作為時間維度供篩選,host般眉、path_list作為普通維度供查詢過濾了赵,session_id和user_id當做metrc算統(tǒng)計值,session_id因為在ETL的時候已經(jīng)去重了甸赃,所以用longSum統(tǒng)計指標即可柿汛,而user_id則考慮用hyperUnique(Hyperloglog算法)求基數(shù)。

數(shù)據(jù)schema設(shè)計

{
  "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",
              "path"
            ]
          },
          "timestampSpec" : {
            "format" : "auto",
            "column" : "time"
          }
        }
      },
      "metricsSpec": [
        {
          "name": "count",
          "type": "count"
        },
        { 
          "type" : "hyperUnique",
          "name" : "qidianid",
          "fieldName" : "qidianid",
          "round" : true
        }
      ]
    },
    "tuningConfig" : {
      "type" : "hadoop",
      "partitionsSpec" : {
        "type" : "hashed",
        "targetPartitionSize" : 5000000
      },
      "indexSpec" : {
        "bitmap" : { "type" : "roaring"},
        "dimensionCompression":"LZ4",
        "metricCompression" : "LZ4",
        "longEncoding" : "auto"
      }
    }
  }
}

三埠对、具體實踐

查詢語句示例

{
  "queryType": "timeseries",
  "dataSource": {
    "type": "table",
    "name": "web_funnel"
  },
  "intervals": {
    "type": "intervals",
    "intervals": ["2018-03-19T00:00:00+08:00/2018-04-19T00:00:00+08:00"]
  },
  "filter": {
    "type": "selector",
    "dimension": "host",
    "value": "qidian.qq.com"
  },
  "granularity": {"type": "all"},
  "aggregations": [
    {
      "type" : "filtered",
      "filter" : {
        "type" : "like",
        "dimension" : "path",
        "pattern": "/%",
        "escape": null,
        "extractionFn": null
      },
      "aggregator" : {"type": "longSum", "name": "1", "fieldName": "count"}
    },
    {
      "type" : "filtered",
      "filter" : {
        "type" : "like",
        "dimension" : "path",
        "pattern": "/ %/index.html%",
        "escape": null,
        "extractionFn": null
      },
      "aggregator" : {"type": "longSum", "name": "2", "fieldName": "count"}
    },
    {
      "type" : "filtered",
      "filter" : {
        "type" : "like",
        "dimension" : "path",
        "pattern": "/ %/index.html %/download.html%",
        "escape": null,
        "extractionFn": null
      },
      "aggregator" : {"type": "longSum", "name": "3", "fieldName": "count"}
    }
  ],
  "context": {"skipEmptyBuckets": true}
}

返回結(jié)果

[{
  "timestamp" : "2018-03-18T16:00:00.000Z",
  "result" : {
    "1" : 434483,
    "2" : 21084,
    "3" : 1479
  }
}]

四络断、實踐效果

測試環(huán)境:

單機:cpu 24 core + 內(nèi)存64gb

查詢延遲:0.5s ~ 2.1s

30天總量(查詢的最長時間范圍,其實時間范圍任選)

原始數(shù)據(jù)量:10,960,000 (千萬級別)

Druid中rollup后數(shù)據(jù)量:1,560,000 (百萬級別)

path基數(shù):1,059,460 (百萬級別)

1天總量(一個segment项玛,查詢的最小粒度)

原始數(shù)據(jù)量:324,850 (十萬級別)

Druid中rollup后數(shù)據(jù)量:56,760 (萬級別)

path基數(shù):55,064 (萬級別)

五貌笨、總結(jié)分析

利用druid做有序漏斗的思路為什么是可行的?為什么其他的存儲引擎不行呢稍计,比如ES躁绸?

熟悉了整套方案后,大家可能會有這方面的疑問臣嚣,那么這里從數(shù)據(jù)分布上來回答這個問題净刮。通常,做搜索匹配可能很容易想到像用ES這樣的搜索架構(gòu)來解決問題硅则,但是這里有幾個特殊點ES不適合

  1. 同一個session下的path做了合并淹父,而ES快是快在分詞后建立對應(yīng)的索引,而該方案是需要把path拼接在一起做全匹配怎虫,這里沒有用的ES的優(yōu)勢而且ES一個string字段最長大小限制是32kb暑认。
  2. 在若是用ES來匹配的話,是需要基于全量數(shù)據(jù)做掃描的大审,所以這里性能不行蘸际。而Druid因為會將原始數(shù)據(jù)相同的維度的行做roll up合并,那么實際在druid中存儲的是聚合合并后的數(shù)據(jù)徒扶。通過觀察數(shù)據(jù)分布粮彤,很多用戶其實只訪問了官網(wǎng)首頁后就離開了,相比其他路徑會有數(shù)據(jù)級的差距姜骡,這里也是發(fā)揮Druid數(shù)據(jù)壓縮的優(yōu)勢导坟。同時,Druid只需要在字典里面查詢出滿足條件的bitmap索引后圈澈,即可快速掃描統(tǒng)計出滿足條件的指標數(shù)惫周。

幾點總結(jié):

  1. 技術(shù)方案無絕對,適合即可康栈。
  2. 關(guān)注數(shù)據(jù)分布递递。
  3. 把控方案成本喷橙。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市漾狼,隨后出現(xiàn)的幾起案子重慢,更是在濱河造成了極大的恐慌,老刑警劉巖逊躁,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件似踱,死亡現(xiàn)場離奇詭異,居然都是意外死亡稽煤,警方通過查閱死者的電腦和手機核芽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酵熙,“玉大人轧简,你說我怎么就攤上這事∝叶” “怎么了哮独?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長察藐。 經(jīng)常有香客問我皮璧,道長,這世上最難降的妖魔是什么分飞? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任悴务,我火速辦了婚禮,結(jié)果婚禮上譬猫,老公的妹妹穿的比我還像新娘讯檐。我一直安慰自己,他們只是感情好染服,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布别洪。 她就那樣靜靜地躺著,像睡著了一般柳刮。 火紅的嫁衣襯著肌膚如雪挖垛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天诚亚,我揣著相機與錄音,去河邊找鬼午乓。 笑死站宗,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的益愈。 我是一名探鬼主播梢灭,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼夷家,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了敏释?” 一聲冷哼從身側(cè)響起库快,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钥顽,沒想到半個月后义屏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蜂大,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年闽铐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奶浦。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡兄墅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出澳叉,到底是詐尸還是另有隱情隙咸,我是刑警寧澤,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布成洗,位于F島的核電站五督,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏泌枪。R本人自食惡果不足惜概荷,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望碌燕。 院中可真熱鬧误证,春花似錦、人聲如沸修壕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慈鸠。三九已至蓝谨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間青团,已是汗流浹背譬巫。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留督笆,地道東北人芦昔。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像娃肿,于是被迫代替她去往敵國和親咕缎。 傳聞我的和親對象是個殘疾皇子珠十,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容