信息圖譜攜程酒店的應(yīng)用
對(duì)于用戶的每一次查詢,都能根據(jù)其意圖做到相應(yīng)的場(chǎng)景和產(chǎn)品的匹配”,是攜程酒店技術(shù)團(tuán)隊(duì)的目標(biāo),但實(shí)現(xiàn)這個(gè)目標(biāo)他們遇到了三大問題…本文著重講述他們是如何構(gòu)建場(chǎng)景與信息關(guān)系,用 Nebula 處理關(guān)聯(lián)關(guān)系,從而快速返回場(chǎng)景化定制推薦信息給酒店用戶的實(shí)踐過程。
背景
用一句話來概述攜程愚公項(xiàng)目的需求便是“對(duì)于用戶的每一次查詢,都能根據(jù)其意圖做到相應(yīng)的場(chǎng)景和產(chǎn)品的匹配”。
目前,在酒店排序方面,攜程酒店已經(jīng)做到了針對(duì)不同的用戶群體和使用場(chǎng)景給出定制化服務(wù):在不同的場(chǎng)景下,酒店列表頁面會(huì)有不同的排序,獲得了很高的用戶價(jià)值提升。而攜程酒店通過在前端展示場(chǎng)景化內(nèi)容,也降低用戶決策的費(fèi)力度。
假如當(dāng)前用戶場(chǎng)景是滑雪度假,作為服務(wù)提供方我們自然期望前端的各個(gè)展示位都能與滑雪相關(guān)聯(lián),如上圖酒店列表頁中酒店的短標(biāo)簽位展示了一個(gè)滑雪套餐
,酒店的榜單位展示的是當(dāng)前酒店在當(dāng)?shù)氐幕┌衽琶?,以及酒店的展示圖片為雪景下的酒店。
酒店詳情頁中,酒店相冊(cè)所展示內(nèi)容也是雪景。相冊(cè)排序第一的分類為【滑雪精選】,而酒店的其他短標(biāo)簽位榜單同列表頁的邏輯類似,展示和滑雪相關(guān)的內(nèi)容。在地理信息位則展示與最近的滑雪場(chǎng)的距離。
上面兩張圖分別是酒店和房型的詳情信息,在酒店設(shè)施、房型氛圍圖內(nèi)容呈現(xiàn)上,也根據(jù)滑雪度假場(chǎng)景做出了相應(yīng)的調(diào)整。
以上 4 張圖,簡(jiǎn)單地描述了攜程酒店對(duì)于前端各個(gè)展示位通過與場(chǎng)景相關(guān)聯(lián)所能達(dá)到的一個(gè)展示的效果。
而要實(shí)現(xiàn)上述功能,首先要把各種場(chǎng)景與內(nèi)容信息之間建立關(guān)聯(lián),輸入場(chǎng)景的時(shí)候就能直接快速地檢索到相關(guān)信息進(jìn)行展示。為此需要解決以下問題:
-
缺乏場(chǎng)景和信息的 mapping 關(guān)系
-
信息的豐富性不夠,無法支撐場(chǎng)景化
-
運(yùn)營和系統(tǒng)不夠高效
具體來說,場(chǎng)景與信息關(guān)聯(lián)關(guān)系缺失的原因是,在愚公項(xiàng)目之前,攜程酒店前端展示內(nèi)容相互獨(dú)立,沒有統(tǒng)一的整合體系。像上面提到的特色標(biāo)簽帶娃
、愛住
標(biāo)簽,設(shè)施標(biāo)簽中親子樂園標(biāo)簽,盡管從語義上能很直接地將它們同親子場(chǎng)景關(guān)聯(lián),但它們一個(gè)是特色,一個(gè)是設(shè)施,除了使用同一個(gè)的展示位之外,標(biāo)簽間并沒有其他的共同點(diǎn)。
另一個(gè)比較典型的例子就是點(diǎn)評(píng),上圖右側(cè) App 截圖是武漢東湖賓館的三條點(diǎn)評(píng),第一條講到親子出行,第二條講到賞櫻內(nèi)容,第三條講到旅游建議,而這三類內(nèi)容目前僅作為一個(gè)酒店點(diǎn)評(píng)展示并沒有其他更多的作用。而在愚公項(xiàng)目中,如果我們定義了三個(gè)場(chǎng)景,一個(gè)叫親子,一個(gè)叫賞櫻,一個(gè)叫旅游,關(guān)聯(lián)點(diǎn)評(píng)與場(chǎng)景標(biāo)簽,那么我們可以做的事情就更多了。比如一家酒店,其中有 30% 點(diǎn)評(píng)提到了親子,可能就可以判斷酒店有親子特色。再比如,提到櫻花的點(diǎn)評(píng)中,抽取出簡(jiǎn)短、優(yōu)美的語句同賞櫻場(chǎng)景關(guān)聯(lián),當(dāng)前端傳過來櫻花場(chǎng)景時(shí),這個(gè)短句子作為展示補(bǔ)充就可以展示在前端位置…諸如類似用途,我們可以天馬行空、不停的想象,但實(shí)現(xiàn)的關(guān)鍵點(diǎn)是建立場(chǎng)景與信息之間的關(guān)聯(lián)。
第二個(gè)問題是信息豐富度不夠,無法支撐場(chǎng)景化需求。舉個(gè)簡(jiǎn)單例子,在列表頁篩選了滑雪后,沒有滑雪相關(guān)的圖片,也沒有相關(guān)標(biāo)簽地理的位置信息;在詳情頁沒有滑雪相關(guān)的相冊(cè)信息,也沒有滑雪的氛圍圖,雖然酒店的設(shè)施有滑雪設(shè)施,但它沒有根據(jù)滑雪這一場(chǎng)景做出更高優(yōu)先級(jí)的展示,第二設(shè)施滑雪設(shè)施也沒有相關(guān)的圖片展示,這樣就導(dǎo)致酒店推薦生動(dòng)性不足。
第三個(gè)問題是系統(tǒng)和運(yùn)營不夠高效。具體來說:
- 新場(chǎng)景 & 新數(shù)據(jù)開發(fā)成本很大。每個(gè)場(chǎng)景上線,需要根據(jù)聯(lián)動(dòng)位置逐個(gè)開發(fā)
- 每個(gè)位置接入新信息,需要跟版本發(fā)布
- 數(shù)據(jù)時(shí)效性:無統(tǒng)一標(biāo)準(zhǔn),時(shí)效性不足
- 例如特色標(biāo)簽,多個(gè) job 串行:T+x 生效
- 數(shù)據(jù)排序:無統(tǒng)一收口方
- 列表頁短標(biāo)簽:靜態(tài)信息、前端均有邏輯+運(yùn)營后臺(tái)
- 排查鏈路長(zhǎng),日常維護(hù)效率低
- 數(shù)據(jù)標(biāo)準(zhǔn):有多套標(biāo)準(zhǔn)存在
- 哪些是親子酒店?
- …
展開來說,攜程酒店前端展示位來源于多個(gè)服務(wù),比如圖中標(biāo)出的這 十多個(gè)展示位,其中就包含點(diǎn)評(píng)、榜單、標(biāo)簽等一系列服務(wù)。如果這些服務(wù)的聯(lián)動(dòng)邏輯,沒有統(tǒng)一收口方,那么每新增一個(gè)場(chǎng)景,相應(yīng)的展示位都需要進(jìn)行相應(yīng)的開發(fā),這樣開發(fā)成本就會(huì)比較大。第二點(diǎn)的數(shù)據(jù)實(shí)時(shí)性,目前更新 job 存在部分串行,部分?jǐn)?shù)據(jù)運(yùn)營修改之后可能在 t+x 之后才能生效,實(shí)時(shí)性不高。第三點(diǎn)是數(shù)據(jù)排序展示邏輯沒有統(tǒng)一的收口方,前后端都有維護(hù)相應(yīng)邏輯的地方,造成冗余信息數(shù)據(jù)、排查鏈路變長(zhǎng)、維護(hù)效率低。最后一點(diǎn)是缺少統(tǒng)一數(shù)據(jù)標(biāo)準(zhǔn)。要判斷酒店是否符合親子特色,怎么做?如果一個(gè)酒店有三個(gè)特色標(biāo)簽提到親子,那么它是否是一家親子酒店呢?又或者酒店點(diǎn)評(píng)中有 20% 內(nèi)容提到了親子,那么它是否是一家親子酒店呢?諸如此類的標(biāo)準(zhǔn),我們需要個(gè)準(zhǔn)確的定義,場(chǎng)景化的規(guī)則才能得以實(shí)施。
總結(jié)來說,要達(dá)到前端各個(gè)展示位內(nèi)容的場(chǎng)景化,需要解決三個(gè)問題,一個(gè)是場(chǎng)景與信息之間缺少關(guān)聯(lián);二是目前的信息豐富度沒有辦法支撐場(chǎng)景化;三是系統(tǒng)的運(yùn)營效率在原有的架構(gòu)下不夠高效。為了解決以上的問題,愚公項(xiàng)目就應(yīng)運(yùn)而生了。
愚公項(xiàng)目:用戶預(yù)訂全流程信息場(chǎng)景化
下圖為愚公項(xiàng)目的總體框架。
項(xiàng)目框架
項(xiàng)目涉及到多個(gè)系統(tǒng)的提升:
- 統(tǒng)一的意圖識(shí)別
- 展示位置邏輯下沉
- 關(guān)系匹配
- 信息挖掘
- 數(shù)據(jù)源豐富
愚公項(xiàng)目主要分為上圖 5 部分內(nèi)容,從上往下第一部分是意圖識(shí)別,主要通過用戶的歷史偏好和實(shí)時(shí)數(shù)據(jù)來識(shí)別用戶的具體意圖,比如用戶他歷史點(diǎn)評(píng)中多次出現(xiàn)了“帶娃”、實(shí)時(shí)的入住篩選項(xiàng)人數(shù)中也有小孩篩選項(xiàng),那么我們判斷他當(dāng)前意圖有很大概率是親子旅游。
第二部分是信息展示邏輯下沉,之前提到前端有十多個(gè)展示位,當(dāng)中的展示邏輯分別有不同的信息服務(wù)維護(hù),在這個(gè)模塊我們將這些展示位的邏輯統(tǒng)一收口,信息之間便能做到聯(lián)動(dòng)。此外,還能達(dá)到去重、去沖突等作用,還可以整體地對(duì)排序召回等邏輯進(jìn)行規(guī)劃。
第三部分是關(guān)系匹配,建立場(chǎng)景與數(shù)據(jù)之間的匹配關(guān)系,這里的數(shù)據(jù)涉及存量的基礎(chǔ)信息數(shù)據(jù),通過挖掘得到的增量數(shù)據(jù)。前期,主要通過人工運(yùn)維的方式將它們與場(chǎng)景建立一個(gè)關(guān)聯(lián),后續(xù)則會(huì)使用 NLP 手段來自動(dòng)建立聯(lián)系。而數(shù)據(jù)與數(shù)據(jù)之間、數(shù)據(jù)與場(chǎng)景之間的這些關(guān)系,則會(huì)使用 Nebula Graph 作為存儲(chǔ)和檢索的媒介。
第四部分是信息挖掘,即從各類的數(shù)據(jù)源中抽取出與場(chǎng)景相關(guān)聯(lián)的信息,又或者是酒店的亮點(diǎn)信息。之前提過的點(diǎn)評(píng)例子,在點(diǎn)評(píng)中找到與場(chǎng)景相關(guān)聯(lián)的句子,從中抽取出通順、優(yōu)美的短句,把它們作為場(chǎng)景化關(guān)聯(lián)的數(shù)據(jù)源,在前端進(jìn)行展示,從而豐富數(shù)據(jù)源。在信息挖掘模塊,總體的流程會(huì)涉及 NLP 相關(guān)的數(shù)據(jù)標(biāo)注、模型訓(xùn)練、badcase 反饋、標(biāo)注再訓(xùn)練。
最后是數(shù)據(jù)源,首先要從盡可能多的數(shù)據(jù)來源中獲取信息,加入圖譜中。當(dāng)然要盡可能保證數(shù)據(jù)的準(zhǔn)確性,直接從源頭而非第三方來獲取數(shù)據(jù)。為了保證準(zhǔn)確性,后續(xù)開發(fā)中可能會(huì)加入反查機(jī)制,比如說某個(gè)酒店有游泳池的設(shè)施展示信息,通過挖掘數(shù)據(jù)發(fā)現(xiàn)這個(gè)酒店當(dāng)前的游泳池設(shè)施早已關(guān)閉,那么我們就可以將數(shù)據(jù)同步給運(yùn)營人員使得數(shù)據(jù)更加的準(zhǔn)確。
上面 5 個(gè)部分,如果將展示位置邏輯的下沉和關(guān)系匹配的建立比作一個(gè)項(xiàng)目的地基,那么其他的模塊則是在項(xiàng)目上建起的高樓,沒有地基哪來的高樓呢?
下面,講解展示位置邏輯的下沉和關(guān)系匹配是如何搭建。
前端信息展示邏輯下沉 & 關(guān)系匹配
模塊的重點(diǎn)是收口前端多個(gè)展示位邏輯的數(shù)據(jù)召回邏輯,建立展示位與場(chǎng)景之間的關(guān)聯(lián)關(guān)系。
具體來說,當(dāng)一個(gè)場(chǎng)景進(jìn)來,系統(tǒng)需要知道哪些展示位要與它聯(lián)動(dòng),相應(yīng)的展示位的數(shù)據(jù)召回邏輯也會(huì)隨之變化。舉個(gè)例子,親子場(chǎng)景,親子游、親子樂園這樣的短標(biāo)簽就可以很好地表達(dá)親子的含義,這時(shí)短標(biāo)簽位就適合直接與親子場(chǎng)景建立關(guān)聯(lián)。而美食場(chǎng)景,某個(gè)酒店在美食榜中名列前茅的話,相對(duì)應(yīng)美食特色標(biāo)簽會(huì)更有說服力,美食場(chǎng)景就更適合同美食榜單進(jìn)行關(guān)聯(lián)。建立關(guān)聯(lián)關(guān)系后,每個(gè)展示位是否需要根據(jù)場(chǎng)景變化,就有了統(tǒng)一的標(biāo)準(zhǔn),進(jìn)而數(shù)據(jù)召回邏輯也就得到了統(tǒng)一。
上表和圖標(biāo)注了 10+ 個(gè)前端展示位和它們的一個(gè)聯(lián)動(dòng)的等級(jí),聯(lián)動(dòng)等級(jí)越高,則代表它展示會(huì)更需要貼合場(chǎng)景化,也更能找到更多的與場(chǎng)景相關(guān)聯(lián)的信息。
上面是場(chǎng)景與展示位之間如何建立關(guān)系,接下來講講場(chǎng)景與數(shù)據(jù)之間又如何建立關(guān)系。上圖比較直觀,首先要挖掘場(chǎng)景,找到凸顯酒店特色或吸引用戶的點(diǎn),接著以場(chǎng)景為基礎(chǔ),找到與場(chǎng)景相聯(lián)動(dòng)的一個(gè)展示位,就像之前提到的不同的展示位可以突出不同的特點(diǎn),場(chǎng)景與合適的展示位關(guān)聯(lián)可以達(dá)到更好的展示效果。最后,通過展示位拓展到相應(yīng)的數(shù)據(jù),而對(duì)應(yīng)的數(shù)據(jù)可能是已存在或者是為特定場(chǎng)景新增的數(shù)據(jù)。
舉例說明下關(guān)系的配置過程,先看一下這張表,現(xiàn)在要定一個(gè)新的滑雪場(chǎng)景,首先得判斷前端哪些展示位可以與這個(gè)場(chǎng)景建立關(guān)聯(lián),找到了酒店的列表頁中快篩短標(biāo)簽、酒店詳情頁中酒店的頭圖點(diǎn)評(píng)等這些展示位,都可以與這個(gè)場(chǎng)景建立聯(lián)動(dòng)。然后,只需要通過這些展示位找到相應(yīng)的數(shù)據(jù)源和數(shù)據(jù)類型,配置關(guān)系即可。
以短標(biāo)簽為例,短標(biāo)簽包含主題標(biāo)簽、設(shè)施標(biāo)簽等,這些數(shù)據(jù)源中可能已經(jīng)存在與滑雪相關(guān)的內(nèi)容,我們可以直接在配置后臺(tái)關(guān)聯(lián)場(chǎng)景關(guān)系。如果不存在相關(guān)內(nèi)容,也可以由運(yùn)營人員進(jìn)行添加,又或者通過數(shù)據(jù)挖掘產(chǎn)生新的數(shù)據(jù)源,再進(jìn)行關(guān)聯(lián)。整個(gè)關(guān)聯(lián)在后臺(tái)十分直觀地進(jìn)行展示,配置完成后,數(shù)據(jù)會(huì)實(shí)時(shí)地寫入到 Nebula Graph 中,前端就可以直接通過滑雪場(chǎng)景篩選到相關(guān)的展示。
支撐信息場(chǎng)景化的技術(shù)架構(gòu)
先從 Nebula 的架構(gòu)和集群部署講起,
這張圖大家一定不陌生,Nebula 服務(wù)包含 graph 服務(wù)、meta 服務(wù)和 storage 這三個(gè)服務(wù)。其中,graph 服務(wù)用于處理客戶端的請(qǐng)求,meta 服務(wù)用于存儲(chǔ)分片、schema、用戶賬號(hào)等等元數(shù)據(jù),storage 則用于存儲(chǔ)圖中的點(diǎn)邊、索引數(shù)據(jù)。
在 Nebula 集群中數(shù)據(jù)一致性是依賴于 raft 協(xié)議,其中 meta 服務(wù)和 storage 服務(wù)都是基于 raft 協(xié)議的集群。而 storage 服務(wù)相較于 meta 服務(wù)結(jié)構(gòu)更為復(fù)雜。具體來說,storage 服務(wù)中每一個(gè)分片的所有副本共同構(gòu)成了一個(gè) raft 集群,也就是說 storage 并不是一個(gè) raft 集群,而是有多少個(gè)分片,它就有多少個(gè) raft 集群。在 raft 集群中由集群中的 leader 來處理請(qǐng)求,而 follower 用來投票選舉、同步數(shù)據(jù)、同步日志,并為 leader 提供一個(gè)候補(bǔ)。leader 會(huì)定時(shí)發(fā)送心跳,如果有一段時(shí)間 follower 沒有接到 leader 發(fā)來的心跳,那么他們就會(huì)自動(dòng)開始選舉并產(chǎn)生新 leader,來自 graph 的請(qǐng)求無論是讀還是寫,基本上由 leader 來響應(yīng)。
由于 raft 協(xié)議特點(diǎn),leader 的投票需要超過半數(shù)以上 follower 投票才能選出,一般集群的部署策略是 2n+1 臺(tái)機(jī)器,這樣可以容忍 n 臺(tái)機(jī)器產(chǎn)生的問題。
機(jī)器部署
攜程酒店的部署方式是三機(jī)房分散比例部署,5n 臺(tái) Storage Service,將它們分散為 1n:2n:2n,這樣任意一個(gè)機(jī)房出問題,另外兩個(gè)機(jī)房都可以繼續(xù)使用。但這樣部署也存在一定的問題,即便是三個(gè)機(jī)房但總體而言其實(shí)只是一個(gè)集群,讀取時(shí)必然存在跨機(jī)房訪問讀取帶來的時(shí)延問題。此外,這種單機(jī)房部署的模式無法支持類似于藍(lán)綠之類的發(fā)布方式,也無法基于就近訪問來分配流量。
這塊,未來攜程酒店的期望是每個(gè)機(jī)房都能部署獨(dú)立集群,做到按集群進(jìn)行流量控制和支持就近訪問。當(dāng)一邊集群故障可直接通過域名流量切換到另一邊的單邊集群,不需要耗費(fèi)太多的切換成本,而寫數(shù)據(jù)的時(shí)候也可以支持藍(lán)綠模式的寫入部署。這個(gè)模式也讓服務(wù)出海變得更為切實(shí)可行,比如在海外直接部署一個(gè)獨(dú)立集群,可大大減少國內(nèi)海外讀取的時(shí)延問題。 這也引出另一個(gè)問題,數(shù)據(jù)同步方面攜程酒店是從國內(nèi)寫海外,在這種情況下,同步的實(shí)時(shí)性和穩(wěn)定性都不能得到很好的保障。攜程酒店也在與攜程系統(tǒng)研發(fā)部團(tuán)隊(duì)討論服務(wù)端之間直接數(shù)據(jù)同步的解決方案,如果能實(shí)現(xiàn)的話,可以更好地減輕數(shù)據(jù)同步產(chǎn)生的時(shí)延影響。 總之,raft 讓 Nebula 方便地應(yīng)對(duì)由機(jī)器本身不可用產(chǎn)生的問題,上面說的新的集群的部署方式,則是在 raft 基礎(chǔ)上讓整個(gè)集群可用性更高,對(duì)于一個(gè)攜程酒店這樣的線上應(yīng)用容錯(cuò)也更加符合實(shí)際的需求。 講完集群的部署問題,接下來講講項(xiàng)目的架構(gòu)。
技術(shù)架構(gòu)
先比較下項(xiàng)目架構(gòu)的前后變化,上圖可以看到原來的架構(gòu)中,客戶端請(qǐng)求的每一種數(shù)據(jù)來源都有其獨(dú)立的場(chǎng)景化配置,部分?jǐn)?shù)據(jù)源由于沒有明確的語義完全沒有辦法支持場(chǎng)景化的配置,這就會(huì)導(dǎo)致三個(gè)主要的問題:
- 開發(fā)繁瑣
- 實(shí)現(xiàn)難度高
- 信息孤島
第一點(diǎn),由于信息展示的邏輯離散、存在多個(gè)獨(dú)立服務(wù),無法形成統(tǒng)一的場(chǎng)景化標(biāo)準(zhǔn)和數(shù)據(jù)召回邏輯,每個(gè)場(chǎng)景化模塊需要單獨(dú)的配置文件和實(shí)現(xiàn)邏輯。第二點(diǎn),像類似酒店圖片、酒店問答等類型內(nèi)容,無法與場(chǎng)景直接建立關(guān)聯(lián),只能單純通過人工運(yùn)營的方式建立關(guān)聯(lián),需要耗費(fèi)很大的成本。第三點(diǎn),各個(gè)信息源的維護(hù)沒有統(tǒng)一的標(biāo)準(zhǔn),信息之間相互獨(dú)立,容易造成不同信息源之間可能有信息重復(fù)或沖突的情況,比如說酒店主題和酒店設(shè)施中包含語義十分相似的標(biāo)簽,如果這兩個(gè)標(biāo)簽同時(shí)展示在前端的話,就會(huì)造成信息冗余的問題。
那么如何解決這些問題呢?要搭建一套可以存儲(chǔ)各類信息與信息之間的關(guān)系,信息與場(chǎng)景之間的關(guān)系,以及將信息召回的邏輯進(jìn)行統(tǒng)一收口的系統(tǒng),我們稱之為信息中臺(tái)系統(tǒng)。
上圖與之前架構(gòu)的區(qū)別,在于把每種數(shù)據(jù)獨(dú)立的場(chǎng)景化配置替換成知識(shí)圖譜模塊跟語義標(biāo)注模塊:知識(shí)圖譜模塊用于存儲(chǔ)信息與信息之間、信息場(chǎng)景之間的關(guān)系,這里我們會(huì)用到 Nebula 。通過 Nebula 建立合適 schema 跟映射關(guān)系,大部分?jǐn)?shù)據(jù)能在兩度以內(nèi)完成查找。語義標(biāo)注模塊則對(duì)語義不明確的信息進(jìn)行挖掘、標(biāo)注,再與場(chǎng)景建立聯(lián)系。像酒店描述信息、酒店問答信息都可從中挖掘有用的數(shù)據(jù),補(bǔ)充進(jìn)知識(shí)圖譜。
上圖略抽象,接下來具體地講講中臺(tái)系統(tǒng)中每一個(gè)模塊的構(gòu)成和功能。
信息中臺(tái)的整體架構(gòu)從右往左可以分成 4 個(gè)模塊,分別是信息中臺(tái) API 模塊、信息圖譜模塊、知識(shí)標(biāo)注模塊和數(shù)據(jù)模塊。
其中,信息中臺(tái) API 模塊是信息中臺(tái)對(duì)客戶端的服務(wù),這個(gè)模塊起到的作用包含場(chǎng)景獲取、數(shù)據(jù)查詢、數(shù)據(jù)包裝,整合數(shù)據(jù)展示邏輯等等。信息中臺(tái) API 讓相冊(cè)、標(biāo)簽、設(shè)備這些服務(wù)由之前的各自包含獨(dú)立的展示邏輯轉(zhuǎn)化為從統(tǒng)一的來源獲取展示邏輯。
知識(shí)圖譜模塊主要整合了數(shù)據(jù)的召回邏輯,使用 Nebula 作為信息之間的一個(gè)存儲(chǔ)引擎,對(duì)于基礎(chǔ)數(shù)據(jù),比如設(shè)施標(biāo)簽數(shù)據(jù),將它們與酒店場(chǎng)景抽象成點(diǎn),將它們之間的關(guān)系抽象成邊。而標(biāo)注產(chǎn)生的數(shù)據(jù)則會(huì)抽象成點(diǎn),與它們與酒店場(chǎng)景之間的關(guān)聯(lián)關(guān)系抽象成邊。當(dāng)輸入場(chǎng)景和酒店 ID 時(shí),通過 Nebula 查詢語句快速地檢索到該酒店下符合場(chǎng)景的所有測(cè)試點(diǎn)的索引信息。另外,通過讀取實(shí)時(shí)消息更新 Nebula 數(shù)據(jù),實(shí)現(xiàn)實(shí)時(shí)更新,而不是 t+x 生效,實(shí)時(shí)性也得到了很大的增強(qiáng)。
信息標(biāo)注模塊大幅度地增加數(shù)據(jù)豐富度,對(duì)大量 UGC、酒店描述內(nèi)容,在其中找到與場(chǎng)景相關(guān)聯(lián)的信息是比較耗費(fèi)資源的工作。這個(gè)時(shí)候,使用 NLP 相關(guān)技術(shù)便能提高效率。上圖中間部分主要畫出了數(shù)據(jù)在整個(gè)信息標(biāo)注模塊中的流轉(zhuǎn)過程。首先預(yù)處理點(diǎn)評(píng)、圖文秀此類信息,得到子句、短句放入標(biāo)注模塊進(jìn)行標(biāo)注。標(biāo)注的時(shí)候,會(huì)使用語義標(biāo)簽,這些語義標(biāo)簽來源于熱搜詞或者人工定義等等渠道。在使用語義標(biāo)簽的時(shí)候,標(biāo)簽會(huì)直接與場(chǎng)景建立關(guān)系,一般情況下這種關(guān)系是一對(duì)一的,但也會(huì)存在一對(duì)多的情況。標(biāo)注好的數(shù)據(jù)會(huì)進(jìn)行模型訓(xùn)練,同靜態(tài)規(guī)則一起進(jìn)入任務(wù)調(diào)度模塊對(duì)數(shù)據(jù)批量地打標(biāo),最后產(chǎn)生的部分?jǐn)?shù)據(jù)進(jìn)行抽樣人工 check 之后就可以使用。這個(gè)信息標(biāo)注模塊整合了數(shù)據(jù)產(chǎn)生的流程,大幅度提升了數(shù)據(jù)產(chǎn)生的效率。
最后,數(shù)據(jù)模塊負(fù)責(zé)的是數(shù)據(jù)整合和傳導(dǎo),模塊數(shù)據(jù)來源包含有信息標(biāo)注模塊產(chǎn)生的各類信息,也包含其他從外部同步來的數(shù)據(jù)。這些數(shù)據(jù)最終通過數(shù)據(jù)同步框架寫入 Nebula Graph 數(shù)據(jù)庫中。
再來講解數(shù)據(jù)在數(shù)據(jù)庫模塊中的流轉(zhuǎn)過程。特色數(shù)據(jù)、設(shè)施數(shù)據(jù)、酒店數(shù)據(jù)等等類型分為全量和增量數(shù)據(jù),全量數(shù)據(jù)包含 DB、消息隊(duì)列、消息接口、Hive 表等等,其中 Hive 表直接通過 Hive job 直接同步 Nebula,而 DB、消息隊(duì)列、消息接口則通過 nebula-java 客戶端同步。攜程酒店結(jié)合 Nebula Java 客戶端實(shí)現(xiàn)了一套可配置化的同步框架,并搭建了信息同步的服務(wù)。當(dāng)數(shù)據(jù)來源是接口、消息隊(duì)列時(shí),通過實(shí)現(xiàn)相應(yīng)的接口組裝數(shù)據(jù),并配置消息字段與 Nebula 字段的映射關(guān)系實(shí)現(xiàn)數(shù)據(jù)同步。當(dāng)數(shù)據(jù)來源是 DB 時(shí),直接用從 DB 中取數(shù) SQL 語句,并配置 DB 字段與 Nebula 字段的映射關(guān)系實(shí)現(xiàn)數(shù)據(jù)同步。增量數(shù)據(jù)主要來源于消息隊(duì)列,增量 job 與全量 job 使用相同映射關(guān)系,對(duì)于增量消息而言只需實(shí)現(xiàn)組裝數(shù)據(jù)的接口即可實(shí)現(xiàn)同步。
除了數(shù)據(jù)同步之外,攜程酒店還有數(shù)據(jù)運(yùn)營的平臺(tái),包含下面 4 個(gè)功能:
-
schema:收口 Nebula schema 操作,Nebula 本身有圖形化界面,攜程酒店將 schema 操作收口到后臺(tái),可便于配置權(quán)限、記錄操作日志。
-
監(jiān)控:在數(shù)據(jù)導(dǎo)入過程中,攜程酒店在 ClickHouse 看板中記錄數(shù)據(jù)、來源、操作類型、主題信息,便于直觀地查看數(shù)據(jù)統(tǒng)計(jì)信息。此外當(dāng)有錯(cuò)誤發(fā)生時(shí),結(jié)合報(bào)錯(cuò)信息中 Nebula query log 加上 CK(ClickHouse)上的數(shù)據(jù),可快速定位到具體點(diǎn)、邊、報(bào)錯(cuò)的類型、數(shù)據(jù)來源、消息 ID 等等信息。
-
依賴配置:在數(shù)據(jù)組裝時(shí),前面提到有數(shù)據(jù)源和 Nebula 字段的映射關(guān)系配置,每次 job 啟動(dòng)會(huì)實(shí)時(shí)讀取映射配置,攜程酒店技術(shù)團(tuán)隊(duì)將配置放到配置后臺(tái),從而實(shí)現(xiàn)實(shí)時(shí)配置實(shí)時(shí)生效。
-
重試機(jī)制:在數(shù)據(jù)傳輸錯(cuò)誤發(fā)生時(shí),加入重試機(jī)制。但消息隊(duì)列這類數(shù)據(jù)本身有重傳的機(jī)制,只需在數(shù)據(jù)異常時(shí)給出相應(yīng)標(biāo)識(shí)。而接口、DB 這類數(shù)據(jù)暫時(shí)沒有重試機(jī)制,后續(xù)會(huì)加入重試機(jī)制。
schema 定義和壓測(cè)
再來講一下 schema 定義和壓測(cè)結(jié)果。
信息中臺(tái)圖譜數(shù)據(jù)模型分為 4 個(gè)大塊,分別是標(biāo)簽信息、基礎(chǔ)信息、UGC 信息和 GEO 信息。標(biāo)簽信息中包含設(shè)施標(biāo)簽、特色標(biāo)簽、長(zhǎng)標(biāo)簽、UGC 標(biāo)簽等這些點(diǎn);基礎(chǔ)信息中包含了房型信息、設(shè)施信息、政策信息等這些點(diǎn);UGC 信息中包含挖掘出的子句點(diǎn)、用戶點(diǎn)等信息;GEO 信息包含了 POI 、省份、城市點(diǎn)等等這些點(diǎn)。酒店作為最中心的點(diǎn)被這 4 塊區(qū)域所包含,同時(shí)與上面提到的每個(gè)點(diǎn)都有相關(guān)聯(lián)的邊。
此外,最上層抽象了語義標(biāo)簽點(diǎn),所有與場(chǎng)景建立關(guān)聯(lián)的點(diǎn)都會(huì)有語義標(biāo)簽直接建立相應(yīng)的邊關(guān)系。這樣,當(dāng)輸入一個(gè)酒店 ID、場(chǎng)景 ID,能很快地篩選出當(dāng)中所有點(diǎn)的信息。這樣的 schema 是比較符合業(yè)務(wù)邏輯的,但在實(shí)際的上線過程中還是出現(xiàn)了些問題,其中比較典型的是熱點(diǎn)數(shù)據(jù)問題。
舉個(gè)例子來說,A 類型數(shù)據(jù)量可能是百萬級(jí),B 類型數(shù)據(jù)量是千級(jí),每一個(gè) A 與 B 之間存在關(guān)聯(lián),那么關(guān)聯(lián)的邊量級(jí)可能在十萬級(jí)或者百萬級(jí),查詢時(shí) B 可能會(huì)變成超級(jí)節(jié)點(diǎn)影響部分性能。
對(duì)此,想過幾個(gè)解決方案。一是增加分片數(shù),用來解決熱點(diǎn)數(shù)據(jù)集中在某一兩臺(tái)機(jī)器中的問題,但這樣只是分散熱點(diǎn),并沒有徹底地解決熱點(diǎn)問題。二是增加邏輯點(diǎn),將某個(gè)熱點(diǎn)分散成多個(gè)屬性相同、但 VID 不同的點(diǎn),這些點(diǎn)同中心點(diǎn)連接時(shí),通過 Hash 或者其他方法把邊打散,但這樣不僅增加了數(shù)據(jù)導(dǎo)入的邏輯復(fù)雜度,在某些情況下還會(huì)影響數(shù)據(jù)與數(shù)據(jù)之間邊本來邏輯的準(zhǔn)確性。也想過 follower 讀這個(gè)方案,由于 raft 協(xié)議的限制,只有 leader 能處理請(qǐng)求,在一致性要求不高的情況下,是否可以支持 follower 處理讀請(qǐng)求,再結(jié)合增加分片數(shù),使整個(gè)集群中的各個(gè)機(jī)器的負(fù)荷能得到大幅度的均衡——這個(gè)問題需要 Nebula 研發(fā)團(tuán)隊(duì)提供技術(shù)支持。
最終,解決熱點(diǎn)問題是在攜程系統(tǒng)研發(fā)部團(tuán)隊(duì)的支持下,通過配置參數(shù)解決了個(gè)別機(jī)器由于熱點(diǎn)數(shù)據(jù)產(chǎn)生的負(fù)載過高的問題——方案是分別開啟前綴匹配布隆過濾器、加大 blockcache。
上表為上線前做的性能測(cè)試圖,集群配置是 6 臺(tái) graph、5 臺(tái) meta、10 臺(tái) storage。在 250+ 萬點(diǎn)、2 億多條邊的情況下,一度查找在 1 萬左右 QPS,在 20 ms左右;同時(shí)寫入 10+ 萬數(shù)據(jù)時(shí),在 40 ms 左右;兩度查找在 7,000 左右 QPS 時(shí),在 32 ms 左右,同時(shí)寫入增量數(shù)據(jù) 10+ 萬時(shí),在 50 ms 左右…總體來說,性能上還是比較符合業(yè)務(wù)需求和預(yù)期。 此外 Nebula 采用天然的分布式架構(gòu)、活躍的中文社區(qū)都是促成攜程酒店最終選擇其作為信息圖譜搭建平臺(tái)基礎(chǔ)設(shè)施的原因之一。
以上為攜程酒店信息知識(shí)圖譜實(shí)踐分享。