據(jù)的智慧旅游推薦與可視化平臺(tái)架構(gòu)實(shí)踐)
做智慧旅游這塊有一陣子了從最初的“拍腦袋熱門(mén)榜”到真正把大數(shù)據(jù)鏈路跑通踩過(guò)的坑確實(shí)不少。這次項(xiàng)目“基于大數(shù)據(jù)的智慧旅游推薦與可視化平臺(tái)”不只是做一張好看的大屏而是把游客行為、景區(qū)承載、消費(fèi)習(xí)慣全部打通讓推薦引擎和大屏展示協(xié)同工作。最終交付的效果是游客打開(kāi)小程序能看到“懂你”的路線(xiàn)景區(qū)管理者能看到實(shí)時(shí)熱力與客流預(yù)測(cè)運(yùn)營(yíng)人員能根據(jù)畫(huà)像調(diào)整營(yíng)銷(xiāo)策略。這篇文章把這套系統(tǒng)的架構(gòu)思路、推薦算法選型、可視化搭建和實(shí)際踩坑記錄下來(lái)希望能給正在做同類(lèi)項(xiàng)目的朋友一些參考。1. 項(xiàng)目整體設(shè)計(jì)與核心思路拆解1.1 明確要解決的業(yè)務(wù)痛點(diǎn)智慧旅游聽(tīng)起來(lái)很宏大落到業(yè)務(wù)層面其實(shí)是三個(gè)非常具體的痛點(diǎn)。第一個(gè)是游客的信息過(guò)載打開(kāi)旅游App滿(mǎn)屏都是“必去榜”“熱門(mén)推薦”但真正符合個(gè)人興趣的內(nèi)容少得可憐年輕人想去小眾文藝地標(biāo)帶娃家庭需要親子友好路線(xiàn)中老年偏好慢節(jié)奏風(fēng)景點(diǎn)一刀切的熱門(mén)榜單根本滿(mǎn)足不了這種差異化需求。第二個(gè)是景區(qū)管理的數(shù)據(jù)盲區(qū)管理者只能靠門(mén)票數(shù)據(jù)事后復(fù)盤(pán)節(jié)假日人流高峰來(lái)時(shí)無(wú)法提前預(yù)警熱門(mén)點(diǎn)位排長(zhǎng)隊(duì)而冷門(mén)區(qū)域無(wú)人問(wèn)津資源調(diào)度全靠經(jīng)驗(yàn)。第三個(gè)是運(yùn)營(yíng)方缺乏精準(zhǔn)營(yíng)銷(xiāo)抓手用戶(hù)明明收藏了某類(lèi)景點(diǎn)卻接到完全無(wú)關(guān)的酒店推送轉(zhuǎn)化率自然上不去。這三個(gè)痛點(diǎn)決定了平臺(tái)不能只做一個(gè)推薦算法或一張大屏而是一個(gè)“數(shù)據(jù)采集-行為建模-個(gè)性化推薦-可視化決策”的完整閉環(huán)。游客端拿到的是千人千面的旅游路線(xiàn)管理端拿到的是客流預(yù)測(cè)與熱力分布運(yùn)營(yíng)端拿到的是基于用戶(hù)畫(huà)像的精準(zhǔn)圈選工具。1.2 技術(shù)選型背后的核心考量項(xiàng)目立項(xiàng)時(shí)我們做過(guò)一次完整的技術(shù)選型對(duì)比。最初考慮過(guò)直接用現(xiàn)成的商業(yè)BI工具做可視化底表數(shù)據(jù)用傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)支撐推薦部分用開(kāi)源推薦系統(tǒng)框架改一改。這個(gè)方案在Demo階段完全夠用但一旦進(jìn)入生產(chǎn)環(huán)境就會(huì)發(fā)現(xiàn)三個(gè)硬傷第一是秒級(jí)實(shí)時(shí)數(shù)據(jù)接入能力不足票務(wù)系統(tǒng)每秒鐘都有新的入園記錄寫(xiě)入商業(yè)BI的實(shí)時(shí)引擎扛不住高頻更新第二是地圖級(jí)別的空間數(shù)據(jù)分析能力弱景區(qū)熱力需要做網(wǎng)格聚合和地理圍欄判斷傳統(tǒng)BI擅長(zhǎng)的是柱狀圖折線(xiàn)圖第三是推薦效果難優(yōu)化開(kāi)源框架默認(rèn)算法難以融入行程順序、交通耗時(shí)這類(lèi)旅游行業(yè)特有的約束條件。最終我們確定了一套Lambda架構(gòu)風(fēng)格的混合技術(shù)棧。數(shù)據(jù)采集層使用Flume和Canal分別處理日志文件和數(shù)據(jù)庫(kù)變更日志統(tǒng)一接入Kafka消息隊(duì)列離線(xiàn)計(jì)算層用Spark做批量ETL處理歷史數(shù)據(jù)挖掘、畫(huà)像標(biāo)簽生成和推薦模型的周期性訓(xùn)練實(shí)時(shí)計(jì)算層用Flink做流式處理計(jì)算實(shí)時(shí)熱門(mén)、擁擠度和在線(xiàn)推薦所需的一些實(shí)時(shí)特征存儲(chǔ)層劃分明確MySQL存儲(chǔ)業(yè)務(wù)元數(shù)據(jù)Redis緩存熱數(shù)據(jù)與實(shí)時(shí)榜單ElasticSearch支撐全文檢索和地理查詢(xún)ClickHouse作為OLAP引擎支撐大屏聚合查詢(xún)可視化層采用ECharts和Leaflet組合前者處理常規(guī)圖表后者處理地圖疊加圖層。這套組合的核心理念是讓不同數(shù)據(jù)找到最合適的計(jì)算和存儲(chǔ)引擎而不是盲目搞“一個(gè)框架打天下”。1.3 影響范圍的提前評(píng)估項(xiàng)目影響面要從三個(gè)角色來(lái)看。對(duì)游客來(lái)說(shuō)推薦結(jié)果直接影響行程滿(mǎn)意度和復(fù)游意愿我們?cè)O(shè)計(jì)時(shí)非常重視推薦結(jié)果的可解釋性每一條推薦路線(xiàn)都會(huì)標(biāo)注“因?yàn)槟阌杏H子標(biāo)簽、偏好自然風(fēng)光所以推薦這條線(xiàn)”。對(duì)管理者來(lái)說(shuō)影響的是應(yīng)急調(diào)度能力和資源分配效率大屏上如果能看到未來(lái)兩小時(shí)的客流預(yù)測(cè)就能提前開(kāi)備用通道或增派疏導(dǎo)人員。對(duì)運(yùn)營(yíng)來(lái)說(shuō)影響的是營(yíng)銷(xiāo)投入回報(bào)率以前投放旅游套餐是廣撒網(wǎng)現(xiàn)在可以根據(jù)用戶(hù)畫(huà)像精準(zhǔn)圈定“喜歡徒步的年輕人”這類(lèi)群體。技術(shù)層面的影響范圍同樣需要提前評(píng)估。數(shù)據(jù)清洗和融合比算法本身更決定項(xiàng)目成敗我們?cè)y(tǒng)計(jì)過(guò)源數(shù)據(jù)中經(jīng)緯度缺失率約12%價(jià)格字段單位不統(tǒng)一的情況超過(guò)5%這些臟數(shù)據(jù)直接進(jìn)算法會(huì)讓推薦質(zhì)量和熱力分布嚴(yán)重失真。所以項(xiàng)目一開(kāi)始就成立了數(shù)據(jù)治理小組制定了統(tǒng)一的景區(qū)編碼、游客ID映射規(guī)則和字段規(guī)范這為后續(xù)所有下游應(yīng)用打好了地基。2. 推薦引擎的實(shí)現(xiàn)細(xì)節(jié)與算法優(yōu)化2.1 基于協(xié)同過(guò)濾的核心推薦邏輯協(xié)同過(guò)濾是整個(gè)推薦系統(tǒng)中用的最多的算法我們同時(shí)實(shí)現(xiàn)了基于用戶(hù)的UserCF和基于物品的ItemCF并針對(duì)旅游場(chǎng)景做了大量適應(yīng)化改造。以ItemCF為例核心邏輯是景區(qū)A和景區(qū)B在大量用戶(hù)行程中經(jīng)常被一同選擇那么當(dāng)新用戶(hù)瀏覽景區(qū)A時(shí)系統(tǒng)會(huì)把景區(qū)B作為相似推薦物推給這個(gè)用戶(hù)。相似度計(jì)算我們使用余弦相似度與共現(xiàn)次數(shù)加權(quán)的混合公式通過(guò)Spark分布式計(jì)算實(shí)現(xiàn)離線(xiàn)更新每日凌晨執(zhí)行一次。ItemCF公式上做了一些細(xì)節(jié)調(diào)整。常規(guī)的余弦相似度只考慮兩個(gè)物品被同一個(gè)用戶(hù)交互的向量夾角這會(huì)造成“熱門(mén)景區(qū)跟任何景區(qū)都相似”的偏差因?yàn)闊衢T(mén)景區(qū)被大量用戶(hù)共同訪問(wèn)共現(xiàn)基數(shù)天然很大。我們引入了一個(gè)懲罰因子使用改進(jìn)的公式similarity |N(i) ∩ N(j)| / sqrt(|N(i)| * |N(j)|) * log(1 1 / (1 cooccurCount))其中cooccurCount代表兩個(gè)景區(qū)的共現(xiàn)次數(shù)當(dāng)共現(xiàn)次數(shù)特別高時(shí)說(shuō)明這種相似關(guān)系很可能只是“因?yàn)槎枷矚g去熱門(mén)”造成的虛假相似懲罰因子會(huì)降低它的權(quán)重。實(shí)測(cè)下來(lái)這個(gè)改進(jìn)讓推薦列表的長(zhǎng)尾內(nèi)容曝光量提升了近百分之四十真正挖掘出了“慕田峪長(zhǎng)城”與“古北水鎮(zhèn)”這類(lèi)真正存在用戶(hù)關(guān)聯(lián)的優(yōu)質(zhì)組合。2.2 冷啟動(dòng)問(wèn)題的分層解決方案推薦系統(tǒng)最容易翻車(chē)的階段是冷啟動(dòng)。新景區(qū)沒(méi)有任何交互數(shù)據(jù)協(xié)同過(guò)濾算不出它跟任何景區(qū)的相似度新用戶(hù)沒(méi)有任何行為歷史協(xié)同過(guò)濾也無(wú)法判斷他喜歡什么。我們?cè)趯?shí)踐中把冷啟動(dòng)拆成三層來(lái)解。第一層是用戶(hù)冷啟動(dòng)依賴(lài)用戶(hù)授權(quán)的基礎(chǔ)信息做統(tǒng)計(jì)型推薦。用戶(hù)首次登錄后我們請(qǐng)求獲取所在城市、出行同行人數(shù)等信息結(jié)合當(dāng)前季節(jié)和節(jié)假日屬性給出一組“初識(shí)偏好”候選集比如“帶娃組合”優(yōu)先推送動(dòng)物園、科技館、主題樂(lè)園類(lèi)內(nèi)容。第二層是物品冷啟動(dòng)新景區(qū)上線(xiàn)后沒(méi)有用戶(hù)數(shù)據(jù)時(shí)依靠?jī)?nèi)容特征計(jì)算相似度。我們對(duì)景區(qū)打了一套多維標(biāo)簽體系包含自然風(fēng)光、歷史人文、親子游樂(lè)、極限挑戰(zhàn)等四十多個(gè)標(biāo)簽維度標(biāo)簽重合度高的景區(qū)會(huì)建立內(nèi)容相似關(guān)系新景區(qū)因此能快速進(jìn)入推薦候選池。第三層是系統(tǒng)級(jí)冷啟動(dòng)針對(duì)沒(méi)有任何數(shù)據(jù)的極端情況使用熱榜策略與實(shí)時(shí)客流兜底。系統(tǒng)在冷啟動(dòng)狀態(tài)下推薦熱門(mén)城市的熱門(mén)景點(diǎn)這個(gè)策略雖然樸素但保證了新用戶(hù)至少能看到一些過(guò)得去的內(nèi)容不至于因?yàn)槭灼撂钪苯恿魇А?.3 行程路線(xiàn)推薦的約束求解單景點(diǎn)推薦只是基礎(chǔ)更貼近真實(shí)需求的是多景點(diǎn)路線(xiàn)推薦。游客不是只想看一個(gè)景區(qū)而是希望一天內(nèi)能玩兩三個(gè)地方且路線(xiàn)順路。這實(shí)際上是個(gè)帶約束的路徑優(yōu)化問(wèn)題。我們把它抽象為給定起始位置和可支配時(shí)長(zhǎng)從候選景區(qū)集合中選擇若干景點(diǎn)使得總旅行時(shí)間消耗不超過(guò)時(shí)間閾值且綜合偏好得分最高。求解時(shí)我們采用了啟發(fā)式算法。先用貪心篩選根據(jù)用戶(hù)偏好得分排序依次檢查加入當(dāng)前路線(xiàn)后是否與已有景點(diǎn)形成回路、路程是否超時(shí)如果超時(shí)則跳過(guò)。貪心結(jié)果作為初解后再用遺傳算法的思路做進(jìn)一步優(yōu)化——把一條路線(xiàn)編碼為一個(gè)景點(diǎn)序列通過(guò)交叉變異迭代若干輪尋找更優(yōu)解。這里的關(guān)鍵優(yōu)化是旅行時(shí)間的估算我們用高德路徑API批量預(yù)計(jì)算了同城景區(qū)兩兩之間的駕車(chē)時(shí)間矩陣離線(xiàn)存儲(chǔ)后在線(xiàn)查詢(xún)時(shí)只需查表不需要實(shí)時(shí)調(diào)API算路徑響應(yīng)速度能壓在兩百毫秒以?xún)?nèi)。2.4 混合推薦與權(quán)重動(dòng)態(tài)調(diào)優(yōu)沒(méi)有單一算法能適配所有場(chǎng)景混合推薦是實(shí)際生產(chǎn)中的必然選擇。我們?cè)O(shè)計(jì)了加權(quán)融合框架最終推薦得分 0.45 * 協(xié)同過(guò)濾得分 0.3 * 內(nèi)容偏好得分 0.15 * 地域與距離得分 0.1 * 實(shí)時(shí)熱度得分。這個(gè)初始權(quán)重組合不是拍腦袋定的而是通過(guò)離線(xiàn)回測(cè)對(duì)比不同權(quán)重組合下的推薦點(diǎn)擊率預(yù)估后確定的。不過(guò)固定權(quán)重在真實(shí)場(chǎng)景中會(huì)失效。回顧一個(gè)具體的例子某個(gè)非熱門(mén)城市的大量用戶(hù)偏好自然風(fēng)光但當(dāng)?shù)刈匀伙L(fēng)光類(lèi)景區(qū)的協(xié)同過(guò)濾得分普遍不高因?yàn)樵擃?lèi)型在當(dāng)?shù)鼗鶖?shù)小、共現(xiàn)數(shù)據(jù)稀疏協(xié)同過(guò)濾的貢獻(xiàn)長(zhǎng)期被高權(quán)重的其他因子壓住。后來(lái)我們把權(quán)重改成了動(dòng)態(tài)化方案——根據(jù)推薦候選集的整體稀疏程度、當(dāng)前時(shí)段等自動(dòng)調(diào)整各模塊權(quán)重在數(shù)據(jù)稀疏的場(chǎng)景下主動(dòng)調(diào)高內(nèi)容偏好的權(quán)重避免協(xié)同過(guò)濾強(qiáng)迫用戶(hù)看重復(fù)熱門(mén)內(nèi)容。這套動(dòng)態(tài)調(diào)優(yōu)上線(xiàn)后推薦列表的整體點(diǎn)擊率提升了大約一成五。2.5 推薦效果評(píng)估的實(shí)踐方法評(píng)估推薦系統(tǒng)的效果最怕只看離線(xiàn)指標(biāo)。離線(xiàn)測(cè)評(píng)我們關(guān)注精確率、召回率、覆蓋率、多樣性四個(gè)維度通過(guò)歷史行為數(shù)據(jù)切分訓(xùn)練集和測(cè)試集來(lái)計(jì)算。但離線(xiàn)指標(biāo)跟線(xiàn)上反饋存在偏差所以上線(xiàn)后我們更看重三個(gè)在線(xiàn)指標(biāo)推薦位點(diǎn)擊率、推薦轉(zhuǎn)化率、用戶(hù)停留時(shí)長(zhǎng)。實(shí)際操作中有一個(gè)很有用的經(jīng)驗(yàn)離線(xiàn)指標(biāo)下降不一定代表產(chǎn)品效果變差。比如我們將推薦列表從“全是熱門(mén)景點(diǎn)”調(diào)整為“熱門(mén)占六成、長(zhǎng)尾占四成”后離線(xiàn)精確率有所下降因?yàn)殚L(zhǎng)尾內(nèi)容點(diǎn)擊率本身不如熱門(mén)高但用戶(hù)平均停留時(shí)長(zhǎng)和路線(xiàn)收藏率明顯上升。這說(shuō)明用戶(hù)是在“逛”推薦內(nèi)容而非“只點(diǎn)第一屏”業(yè)務(wù)價(jià)值其實(shí)更高。后來(lái)我們統(tǒng)一了評(píng)估標(biāo)準(zhǔn)以大屏上監(jiān)控的周維度轉(zhuǎn)化漏斗為北極星指標(biāo)不再被單一日活或單次點(diǎn)擊率綁架。3. 數(shù)據(jù)管道與實(shí)時(shí)計(jì)算架構(gòu)3.1 埋點(diǎn)體系與數(shù)據(jù)接入設(shè)計(jì)推薦和可視化是否準(zhǔn)確根基取決于埋點(diǎn)質(zhì)量和接入能力。埋點(diǎn)設(shè)計(jì)時(shí)我們統(tǒng)一規(guī)劃了各端點(diǎn)的標(biāo)準(zhǔn)事件模型。游客端埋點(diǎn)需要覆蓋的關(guān)鍵事件包括啟動(dòng)、搜索、曝光、詳情頁(yè)查看、收藏、路線(xiàn)規(guī)劃、下單、評(píng)價(jià)等每個(gè)事件必須攜帶用戶(hù)ID、景區(qū)ID、操作時(shí)間、操作系統(tǒng)、GPS經(jīng)緯度等上下文信息。景區(qū)閘機(jī)數(shù)據(jù)通過(guò)數(shù)據(jù)同步工具對(duì)接票務(wù)系統(tǒng)運(yùn)營(yíng)后臺(tái)的訂單數(shù)據(jù)通過(guò)監(jiān)聽(tīng)數(shù)據(jù)庫(kù)變更日志獲取。所有采集任務(wù)統(tǒng)一追加到KafkaKafka里的數(shù)據(jù)既是離線(xiàn)批處理的源也是實(shí)時(shí)流處理的源一魚(yú)兩吃。這個(gè)環(huán)節(jié)最值得提醒的是埋點(diǎn)方案一定要在需求評(píng)審階段就確定字段規(guī)范而不是二次開(kāi)發(fā)時(shí)再補(bǔ)。我們?cè)?jīng)漏掉了“從哪個(gè)推薦位點(diǎn)擊”這個(gè)關(guān)鍵字段導(dǎo)致后續(xù)想分析推薦位效果時(shí)數(shù)據(jù)缺失只能等新版本發(fā)版后重新累計(jì)數(shù)據(jù)白白浪費(fèi)一個(gè)月的驗(yàn)證周期。3.2 離線(xiàn)與實(shí)時(shí)計(jì)算的分工協(xié)作離線(xiàn)計(jì)算承擔(dān)了畫(huà)像標(biāo)簽體系、離線(xiàn)推薦模型、歷史趨勢(shì)報(bào)表三類(lèi)任務(wù)。用Spark定期執(zhí)行例如每日凌晨計(jì)算全量用戶(hù)的長(zhǎng)短期偏好標(biāo)簽包括偏好景點(diǎn)類(lèi)型、偏好出游時(shí)段、人均消費(fèi)力級(jí)別、親子或戶(hù)外等特殊標(biāo)簽。離線(xiàn)任務(wù)的核心價(jià)值在于覆蓋面廣、計(jì)算量大但容忍延遲適合做特征工程和模型訓(xùn)練。實(shí)時(shí)計(jì)算則聚焦三塊核心場(chǎng)景。第一是熱力檢測(cè)根據(jù)當(dāng)前周期內(nèi)景區(qū)入園記錄和游客GPS位置計(jì)算實(shí)時(shí)客流密度區(qū)域人口密度超過(guò)安全閾值時(shí)自動(dòng)觸發(fā)預(yù)警第二是實(shí)時(shí)推薦特征更新用戶(hù)最近十分鐘點(diǎn)擊了哪類(lèi)景區(qū)該行為要快速反映到推薦候選池重排中第三是實(shí)時(shí)榜單熱門(mén)城市TOP10榜單要能秒級(jí)刷新。實(shí)時(shí)鏈路我們用Flink實(shí)現(xiàn)Kafka中的數(shù)據(jù)通過(guò)Flink進(jìn)行窗口聚合。比如計(jì)算五分鐘窗口的景區(qū)熱度Flink會(huì)在每五秒進(jìn)行一次滑窗計(jì)算將結(jié)果更新到Redis可視化端每三十秒輪詢(xún)一次Redis換取最新數(shù)據(jù)。技術(shù)上有一點(diǎn)需要注意Flink開(kāi)啟checkpoint后如果并發(fā)過(guò)大容易導(dǎo)致反壓我們通過(guò)調(diào)整并行度和緩沖區(qū)大小解決了這個(gè)隱患。3.3 數(shù)據(jù)倉(cāng)庫(kù)的分層設(shè)計(jì)數(shù)據(jù)倉(cāng)庫(kù)設(shè)計(jì)是整套平臺(tái)的信息中樞。我們用Hive搭建了離線(xiàn)數(shù)倉(cāng)整體分為三層。ODS層存放原始數(shù)據(jù)與原系統(tǒng)保持一致性不做任何加工只是按天分區(qū)DWD層做維度建模和清洗解決數(shù)據(jù)口徑不一致、字段缺失、重復(fù)記錄問(wèn)題比如把各個(gè)來(lái)源的景區(qū)名稱(chēng)統(tǒng)一映射到標(biāo)準(zhǔn)景區(qū)編碼體系上ADS層直接面向應(yīng)用這里存放的是推薦服務(wù)要用的用戶(hù)畫(huà)像寬表、大屏查詢(xún)要用的城市聚合指標(biāo)結(jié)果、實(shí)時(shí)榜單要用的熱門(mén)景區(qū)表等。ADS層的結(jié)果經(jīng)過(guò)數(shù)據(jù)同步工具導(dǎo)出到ClickHouse供大屏端秒級(jí)OLAP查詢(xún)使用。個(gè)人感受是數(shù)倉(cāng)分層寧可一開(kāi)始規(guī)范些也不要圖省事。我們?cè)驗(yàn)橼s進(jìn)度在ODS和DWD之間壓縮了路徑導(dǎo)致后期兩個(gè)口徑對(duì)不上排查問(wèn)題多花了將近一周這種代價(jià)比老老實(shí)實(shí)多建一層表要貴得多。3.4 核心指標(biāo)體系的定義邏輯可視化大屏不能只堆砌羅列數(shù)據(jù)必須有一套能真正指導(dǎo)決策的指標(biāo)體系。最終上線(xiàn)的指標(biāo)庫(kù)包含四類(lèi)、二十多項(xiàng)指標(biāo)這里說(shuō)幾個(gè)比較有代表性的??土髁渴腔A(chǔ)指標(biāo)粒度細(xì)化到城市、景區(qū)、小時(shí)客流預(yù)測(cè)指標(biāo)基于歷史客流曲線(xiàn)和節(jié)假日參數(shù)做時(shí)間序列預(yù)測(cè)輸出未來(lái)一小時(shí)和未來(lái)三小時(shí)的客流區(qū)間熱度指數(shù)是實(shí)時(shí)客流與歷史同期平均值的比值大于1.5會(huì)預(yù)警為擁擠狀態(tài)游客畫(huà)像分布在景區(qū)管理者視角中呈現(xiàn)的是年齡段、客源地、停留時(shí)長(zhǎng)、消費(fèi)標(biāo)簽的分布情況。消費(fèi)洞察是整個(gè)指標(biāo)體系中業(yè)務(wù)方最關(guān)注的。我們將景區(qū)周邊商戶(hù)支付數(shù)據(jù)脫敏后聚合圈定出不同客源地游客在美食、住宿、娛樂(lè)方面的消費(fèi)偏好和平均消費(fèi)金額從而生成“城市-客源地-消費(fèi)傾向”三位一體的分析視圖。這些指標(biāo)的定義過(guò)程本身就是一次業(yè)務(wù)對(duì)齊研發(fā)和運(yùn)營(yíng)團(tuán)隊(duì)反復(fù)磨合后才統(tǒng)一了“活躍用戶(hù)”“停留時(shí)長(zhǎng)”等名詞的含義避免上線(xiàn)后出現(xiàn)“系統(tǒng)顯示的數(shù)據(jù)和業(yè)務(wù)理解的不一致”的尷尬。4. 可視化大屏的內(nèi)容規(guī)劃與實(shí)現(xiàn)路徑4.1 大屏布局邏輯與信息層級(jí)設(shè)計(jì)可視化大屏是整個(gè)項(xiàng)目對(duì)外展示的“門(mén)面”也是決策者用得最多的功能模塊。布局規(guī)劃上我們沒(méi)有把一堆圖表塞進(jìn)一塊屏幕而是依照“總覽到細(xì)分、宏觀到微觀”的原則做了信息層級(jí)設(shè)計(jì)。整個(gè)大屏按九宮格思路規(guī)劃了核心區(qū)域。頂部區(qū)域是全局總覽展示全國(guó)熱門(mén)城市排行、今日總客流、同比增長(zhǎng)率等宏觀數(shù)據(jù)中間區(qū)域是主體地圖展示已接通城市和景區(qū)的空間分布左右兩側(cè)是主題面板左側(cè)聚焦游客畫(huà)像和推薦效果數(shù)據(jù)右側(cè)展示熱門(mén)景區(qū)榜單和實(shí)時(shí)預(yù)警信息底部區(qū)域?yàn)闀r(shí)間趨勢(shì)分析和輿情關(guān)鍵詞云。為了讓管理者從大屏上快速讀到一個(gè)關(guān)鍵結(jié)論——比如“華東區(qū)域客流驟增需要關(guān)注”——我們?cè)诘貓D區(qū)疊加了預(yù)警徽標(biāo)并配合顏色聯(lián)動(dòng)提示緊急程度。4.2 地圖組件與圖層疊加的實(shí)現(xiàn)技巧地圖可視化是整個(gè)大屏開(kāi)發(fā)過(guò)程中最具挑戰(zhàn)性的部分。旅游數(shù)據(jù)天然帶坐標(biāo)屬性所有指標(biāo)幾乎都要落到地理維度上。我們選用了Leaflet作為底層地圖引擎疊加不同業(yè)務(wù)圖層??土鞣植紵崃D是最核心的圖層。我們基于景區(qū)坐標(biāo)和高德逆地理編碼得到區(qū)域聚合數(shù)據(jù)實(shí)時(shí)數(shù)據(jù)從接口取到后累加為熱力圖權(quán)重值再利用WebGL渲染熱力效果。實(shí)測(cè)中有一個(gè)性能瓶頸上萬(wàn)級(jí)數(shù)據(jù)點(diǎn)時(shí)Canvas渲染會(huì)出現(xiàn)明顯卡頓優(yōu)化方案是服務(wù)端先做網(wǎng)格聚合前端只渲染網(wǎng)格聚合后的點(diǎn)而不是把全部原始點(diǎn)推到瀏覽器內(nèi)。地圖散點(diǎn)與飛線(xiàn)圖處理的是城市間或景區(qū)間的關(guān)聯(lián)關(guān)系飛線(xiàn)用于展示客源地與目的地間的出行流量流向方便判斷哪些城市是核心客源地。GeoJSON數(shù)據(jù)的加載效率也是大屏交互體驗(yàn)的關(guān)鍵。我們最初加載的是完整省級(jí)行政區(qū)邊界數(shù)據(jù)文件體積大、解析慢后來(lái)使用壓縮處理保留必要精度等級(jí)地圖首頁(yè)渲染時(shí)間從接近三秒降到了約一秒。Leaflet在使用過(guò)程中還有個(gè)小技巧當(dāng)?shù)貓D底圖和業(yè)務(wù)圖層是兩個(gè)獨(dú)立容器以后業(yè)務(wù)圖層刷新不會(huì)導(dǎo)致整個(gè)地圖重新加載數(shù)據(jù)更新效率高很多。4.3 動(dòng)態(tài)圖表與時(shí)間軸聯(lián)動(dòng)的交互體驗(yàn)靜態(tài)展示容易讓人失去耐心大屏必須支持交互探索。我們?cè)O(shè)計(jì)了兩個(gè)關(guān)鍵的交互能力。第一個(gè)是時(shí)間軸聯(lián)動(dòng)。用戶(hù)拖動(dòng)屏幕上代表時(shí)間段的時(shí)間軸滑塊下方的客流曲線(xiàn)圖、景區(qū)熱度排行、地圖熱力圖層會(huì)同時(shí)更新到對(duì)應(yīng)時(shí)間點(diǎn)的數(shù)據(jù)。這個(gè)功能在復(fù)盤(pán)某次節(jié)假日客流波動(dòng)時(shí)非常有用管理者可以直觀看到早上九點(diǎn)開(kāi)園時(shí)的客流尖峰以及下午三點(diǎn)的人群轉(zhuǎn)移趨勢(shì)。實(shí)現(xiàn)上我們做了一個(gè)大屏狀態(tài)管理機(jī)制時(shí)間維度作為全局狀態(tài)所有組件監(jiān)聽(tīng)狀態(tài)變化后重新拉取對(duì)應(yīng)時(shí)間切片的數(shù)據(jù)。第二個(gè)是聯(lián)動(dòng)篩選。點(diǎn)擊地圖上某個(gè)省份左側(cè)游客畫(huà)像面板自動(dòng)切換為該省份的數(shù)據(jù)推薦效果面板相應(yīng)更新為該省份用戶(hù)在推薦位的互動(dòng)數(shù)據(jù)。這種國(guó)家、省、市三級(jí)下鉆的聯(lián)動(dòng)模式讓整個(gè)大屏從“看”變成了“用”管理者不需要自己費(fèi)勁去比對(duì)不同區(qū)域的差異。4.4 可視化性能優(yōu)化的幾個(gè)硬核手段性能優(yōu)化是可視化項(xiàng)目維護(hù)階段的重要課題。大屏要達(dá)到流暢的交互體驗(yàn)必須解決三個(gè)層面的問(wèn)題數(shù)據(jù)量大、渲染開(kāi)銷(xiāo)高、查詢(xún)響應(yīng)慢。數(shù)據(jù)層優(yōu)化主要在服務(wù)端完成。ClickHouse的聚合查詢(xún)能力很強(qiáng)但對(duì)千萬(wàn)級(jí)數(shù)據(jù)的明細(xì)查詢(xún)壓力依然很大。我們的做法是預(yù)聚合在ADS層建立不同維度組合的物化結(jié)果表大屏查詢(xún)盡可能命中預(yù)聚合數(shù)據(jù)只有在做下鉆分析時(shí)才允許明細(xì)查詢(xún)。渲染層優(yōu)化主要在前端完成。除了前面提到的網(wǎng)格聚合外我們還大量使用了Canvas而非DOM節(jié)點(diǎn)來(lái)渲染散點(diǎn)DOM節(jié)點(diǎn)在幾百個(gè)以下勉強(qiáng)可行到了上千個(gè)就會(huì)出現(xiàn)明顯卡頓。ECharts在渲染大量數(shù)據(jù)時(shí)可以切換到流式渲染模式并通過(guò)關(guān)閉動(dòng)畫(huà)減少每幀的CPU開(kāi)銷(xiāo)。請(qǐng)求層優(yōu)化比較容易被忽視。統(tǒng)一封裝了數(shù)據(jù)請(qǐng)求模塊對(duì)相同參數(shù)請(qǐng)求做了緩存復(fù)用地圖縮放過(guò)程中的連續(xù)請(qǐng)求會(huì)被合并。實(shí)測(cè)光這兩項(xiàng)就減少了大屏端約三成的無(wú)效請(qǐng)求。5. 系統(tǒng)部署與運(yùn)維實(shí)戰(zhàn)復(fù)盤(pán)5.1 環(huán)境規(guī)劃與集群部署策略系統(tǒng)部署環(huán)節(jié)我們規(guī)劃了三類(lèi)環(huán)境開(kāi)發(fā)環(huán)境、測(cè)試環(huán)境和生產(chǎn)環(huán)境。生產(chǎn)環(huán)境的硬件規(guī)劃綜合考慮了成本和性能三臺(tái)計(jì)算節(jié)點(diǎn)組成Hadoop集群跑離線(xiàn)任務(wù)兩臺(tái)Flink節(jié)點(diǎn)承擔(dān)實(shí)時(shí)計(jì)算一臺(tái)ClickHouse節(jié)點(diǎn)支撐大屏查詢(xún)一臺(tái)MySQL節(jié)點(diǎn)存儲(chǔ)業(yè)務(wù)數(shù)據(jù)前端服務(wù)與推薦服務(wù)分別獨(dú)立部署。部署過(guò)程中用Docker容器化所有有狀態(tài)和無(wú)狀態(tài)服務(wù)統(tǒng)一采用編排平臺(tái)管理。在資源分配上剛開(kāi)始因?yàn)閷?duì)內(nèi)存需求預(yù)估不足出現(xiàn)過(guò)多次Flink任務(wù)因堆內(nèi)存溢出被反復(fù)重啟的情況后來(lái)為每個(gè)Flink任務(wù)單獨(dú)配置了資源限制并把JVM參數(shù)調(diào)優(yōu)后才穩(wěn)定運(yùn)營(yíng)。5.2 數(shù)據(jù)質(zhì)量監(jiān)控與異常告警機(jī)制平臺(tái)運(yùn)行一段時(shí)間后發(fā)現(xiàn)數(shù)據(jù)本身是會(huì)“生病”的。埋點(diǎn)數(shù)據(jù)源偶爾會(huì)因?yàn)锳pp版本升級(jí)導(dǎo)致字段解析異常第三方API偶爾超時(shí)會(huì)造成數(shù)據(jù)缺失如果不監(jiān)控?cái)?shù)據(jù)質(zhì)量可視化大屏上就會(huì)顯示異常數(shù)據(jù)管理者一旦誤判損失不可估量。我們建立了一套數(shù)據(jù)質(zhì)量監(jiān)控體系。對(duì)流量類(lèi)指標(biāo)設(shè)置了偏差告警規(guī)則如果實(shí)時(shí)統(tǒng)計(jì)值與歷史同期值的偏差超過(guò)設(shè)定閾值便自動(dòng)告警。對(duì)畫(huà)像標(biāo)簽做了覆蓋率監(jiān)控標(biāo)簽覆蓋率低于預(yù)期說(shuō)明埋點(diǎn)可能丟失。對(duì)數(shù)據(jù)接入鏈路監(jiān)控更嚴(yán)格Kafka消費(fèi)組積壓超過(guò)一定閾值說(shuō)明實(shí)時(shí)鏈路滯后系統(tǒng)自動(dòng)發(fā)告警到值班群。5.3 推薦服務(wù)的性能調(diào)優(yōu)與穩(wěn)定性保障推薦服務(wù)是要支撐線(xiàn)上請(qǐng)求的性能與穩(wěn)定性直接影響用戶(hù)體驗(yàn)。上線(xiàn)初期的性能瓶頸出現(xiàn)在兩個(gè)地方一是用戶(hù)畫(huà)像實(shí)時(shí)更新導(dǎo)致的查詢(xún)壓力大二是路線(xiàn)推薦計(jì)算中的路線(xiàn)距離計(jì)算耗時(shí)過(guò)長(zhǎng)。針對(duì)第一個(gè)問(wèn)題我們將畫(huà)像讀取改為兩級(jí)緩存熱數(shù)據(jù)存Redis全量畫(huà)像定期落HBase。推薦請(qǐng)求先從Redis取實(shí)時(shí)特征如果命中則直接參與計(jì)算否則回源到HBase讀取全量畫(huà)像再組裝。針對(duì)第二個(gè)問(wèn)題我們提前將熱門(mén)城市內(nèi)部景區(qū)兩兩距離矩陣全部離線(xiàn)預(yù)計(jì)算好在線(xiàn)計(jì)算時(shí)直接查表獲取。穩(wěn)定性層面做了降級(jí)方案。當(dāng)推薦服務(wù)自身的依賴(lài)出現(xiàn)異常時(shí)自動(dòng)降級(jí)為用戶(hù)所在地的熱門(mén)景區(qū)列表雖然推薦精度暫時(shí)變低但至少能保證接口正常工作不會(huì)把用戶(hù)拒之門(mén)外。5.4 常見(jiàn)故障排查與處理實(shí)錄這里記錄幾個(gè)實(shí)際項(xiàng)目中遇到并解決的典型故障供參考排查。Kafka消費(fèi)延遲突增是最常見(jiàn)的故障類(lèi)型。某次實(shí)時(shí)指標(biāo)顯示客流數(shù)據(jù)滯后二十分鐘排查時(shí)發(fā)現(xiàn)是某個(gè)分區(qū)內(nèi)一條畸形數(shù)據(jù)導(dǎo)致消費(fèi)者線(xiàn)程不斷重試阻塞了后面的消息處理。處理方案是先跳過(guò)該條消息同時(shí)給數(shù)據(jù)清洗層增加針對(duì)異常數(shù)據(jù)的容錯(cuò)邏輯后續(xù)類(lèi)似問(wèn)題沒(méi)有再發(fā)生。ClickHouse查詢(xún)偶爾出現(xiàn)超時(shí)的問(wèn)題也值得一提。運(yùn)行一段時(shí)間后發(fā)現(xiàn)某張大屏所需時(shí)間跨度較長(zhǎng)的SQL查詢(xún)達(dá)到了未經(jīng)過(guò)優(yōu)化的瓶頸后來(lái)將查詢(xún)條件中加上日期分區(qū)限定并做物化視圖查詢(xún)速度大幅提升。這類(lèi)問(wèn)題的排查思路很明確優(yōu)先確認(rèn)是否命中了分區(qū)裁剪其次確認(rèn)是否命中了主鍵索引然后再排查SQL寫(xiě)法是否過(guò)濾條件過(guò)多。Flink任務(wù)反壓?jiǎn)栴}幾乎每隔一段時(shí)間就會(huì)遇到一次。癥狀表現(xiàn)為Kafka消費(fèi)組積壓持續(xù)上升實(shí)時(shí)數(shù)據(jù)不再實(shí)時(shí)。處理經(jīng)驗(yàn)是先降低單并行度實(shí)例的負(fù)荷確認(rèn)是否單算子成為熱點(diǎn)再檢查下游存儲(chǔ)寫(xiě)入性能。我們有一回發(fā)現(xiàn)問(wèn)題出在下游ClickHouse批量插入每次量太大觸發(fā)寫(xiě)入限流后來(lái)把批量大小調(diào)低后反壓自然恢復(fù)。6. 客戶(hù)價(jià)值復(fù)盤(pán)與后續(xù)迭代方向6.1 分角色價(jià)值落地的真實(shí)反饋系統(tǒng)上線(xiàn)三個(gè)月后做過(guò)一次使用反饋收集各角色的反饋很能說(shuō)明問(wèn)題。景區(qū)管理者最認(rèn)可的是客流預(yù)測(cè)功能雖然剛開(kāi)始預(yù)測(cè)準(zhǔn)確率只有百分之七十多但對(duì)于判斷是否需要提前調(diào)度人力來(lái)說(shuō)已經(jīng)足夠運(yùn)營(yíng)團(tuán)隊(duì)認(rèn)為游客畫(huà)像和推薦效果的聯(lián)動(dòng)分析幫他們找到了高價(jià)值人群某一輪套餐營(yíng)銷(xiāo)的人群定向投放轉(zhuǎn)化率比以往粗放投放翻了一倍游客側(cè)的滿(mǎn)意度調(diào)查顯示使用推薦路線(xiàn)的用戶(hù)比隨機(jī)瀏覽用戶(hù)平均停留時(shí)長(zhǎng)高出不少推薦中的可解釋標(biāo)簽很加分。客觀來(lái)說(shuō)也有不足。部分小城市、偏遠(yuǎn)景區(qū)的數(shù)據(jù)覆蓋度不夠?qū)е吕鋯?dòng)推薦還是經(jīng)常落到頭部熱門(mén)景區(qū)長(zhǎng)尾景區(qū)的推薦時(shí)機(jī)和策略還有優(yōu)化空間。語(yǔ)音交互和智能問(wèn)答也因?yàn)轵?yàn)收周期原因暫時(shí)沒(méi)有上生產(chǎn)環(huán)境留到了后續(xù)迭代版本。6.2 從單體推薦向智能決策升級(jí)技術(shù)迭代方向上推薦系統(tǒng)正從單純的“給用戶(hù)推什么”向“給管理者建議做什么”演化。接下來(lái)的規(guī)劃是多目標(biāo)優(yōu)化不再只看點(diǎn)擊率而是綜合游客滿(mǎn)意度、景區(qū)接待能力、區(qū)域消費(fèi)拉動(dòng)效應(yīng)做多目標(biāo)平衡推薦結(jié)果要兼顧“游客喜歡”和“便于管理者疏導(dǎo)”兩個(gè)維度。大屏端也在升級(jí)從結(jié)果展示型向“診斷-歸因-建議”型發(fā)展。管理者點(diǎn)擊某區(qū)域的異??土鞲婢瘯r(shí)系統(tǒng)能自動(dòng)解釋可能原因比如附近在舉辦大型活動(dòng)或天氣突變導(dǎo)致游客聚集并給出對(duì)應(yīng)的疏導(dǎo)建議。這意味著系統(tǒng)不僅展示最終結(jié)論還能呈現(xiàn)推導(dǎo)過(guò)程這個(gè)能力對(duì)于提升管理者的信任度非常重要。6.3 數(shù)據(jù)資產(chǎn)的長(zhǎng)線(xiàn)復(fù)用思考最后想聊一點(diǎn)更長(zhǎng)遠(yuǎn)的東西。這類(lèi)平臺(tái)建設(shè)過(guò)程中積累的數(shù)據(jù)資產(chǎn)其價(jià)值遠(yuǎn)不止用于推薦和可視化。游客行為數(shù)據(jù)沉淀下來(lái)的城市偏好、消費(fèi)習(xí)慣、游線(xiàn)模式本身就是具有商業(yè)價(jià)值的數(shù)據(jù)資產(chǎn)。我們可以基于這些數(shù)據(jù)為本地文旅部門(mén)提供中長(zhǎng)期游客趨勢(shì)評(píng)估和產(chǎn)品規(guī)劃輔助決策服務(wù)也可以為城市旅游品牌營(yíng)銷(xiāo)提供數(shù)據(jù)洞察支撐。項(xiàng)目投入最大的不只是算法和可視化數(shù)據(jù)治理和數(shù)據(jù)資產(chǎn)的沉淀才是最值得長(zhǎng)期維護(hù)的部分。我在實(shí)際項(xiàng)目中體會(huì)最深的一點(diǎn)是技術(shù)架構(gòu)再?gòu)?fù)雜最終還是要回答“這個(gè)數(shù)據(jù)準(zhǔn)不準(zhǔn)”和“這個(gè)結(jié)論能不能用”這兩個(gè)樸素問(wèn)題。團(tuán)隊(duì)能持續(xù)拿數(shù)據(jù)說(shuō)話(huà)、拿效果說(shuō)話(huà)項(xiàng)目才有持續(xù)建設(shè)下去的生命力。這套“數(shù)據(jù)采集-推薦引擎-可視化決策”的思路后續(xù)換到其他垂直領(lǐng)域比如智慧會(huì)展、智慧商圈導(dǎo)流整體框架遷移成本也很低這也是當(dāng)初設(shè)計(jì)時(shí)堅(jiān)持分層解耦帶來(lái)的紅利。