机票垂直搜索引擎的性能优化
我們先了解一下機票的行業(yè)背景,下圖是由中航信統(tǒng)計的數(shù)據(jù),藍色的曲線代表平均每公里的票價,紅色曲線指的是客運量。從2011年到2016年,無論是國內、港澳臺還是國際,整體趨勢都是機票價格便宜了,坐飛機的人也越來越多了。特別是國際機票,這五年里機票價格下降30%,客運量增長了140%。
乘客越來越多,購買機票的渠道有哪些呢?現(xiàn)在主要有三個:網絡平臺、代售點和航司官網。像攜程、去哪兒、飛豬、同程等,是主流的網絡購票平臺;像旅行社這類代售點,是旅行團的主要購票渠道;同時大部分航空公司的官網也可以購票,而且有相對較低的價格。總體來說,網絡平臺是最大的銷售渠道,占比76%。為什么網絡平臺占有這么大的份額呢,主要原因是機票垂直搜索引擎是主要的用戶流量入口,用戶一般是先比價然后再去預訂,一個好的機票搜索引擎查詢的產品豐富、價格便宜,而且響應速度快,運價也準,這些特性在技術方面實現(xiàn)好并不容易。
二、主要問題與解決方案機票查詢要快、準、低。快是指查詢快,能夠提供一個良好的用戶體驗;準是指運價準,可以保證出票的成功率;低是指票價低,能夠吸引更多的用戶。但是,如果票價要有優(yōu)勢,就要有大量產品,產品數(shù)據(jù)多了查詢就慢,如果查詢要快,就必須要緩存,但是數(shù)據(jù)緩存了,運價就可能不準。這三者是矛盾的,類似于CAP原則,具體示意圖如下:
對于以上問題,怎么解決呢?通用的三個技術方案有:一、用DB+Redis平衡響應速度、數(shù)據(jù)實時性和查詢成本;二、用削峰填谷的MQ來處理高并發(fā);三、將業(yè)務服務化、模塊解耦。這些只是通用的技術點,并沒有什么難度,我們這里重點介紹與最終結果密切相關的四個模塊:靜態(tài)數(shù)據(jù)、緩存策略、實時查詢、政策匹配。
機票查詢的靜態(tài)數(shù)據(jù)主要有:城市、機型、航司、運價數(shù)據(jù)等,這里重點介紹較為復雜的運價數(shù)據(jù),運價數(shù)據(jù)的獲取雖然間隔時間較長,但數(shù)據(jù)量大且更新頻次不同。運價數(shù)據(jù)是由中航信統(tǒng)一提供的,有兩種途徑:黑屏查詢和IBE接口,將獲取到的數(shù)據(jù)保存到數(shù)據(jù)庫和緩存中,用戶查詢的時候直接從緩存中獲取,同時也會按照一定的緩存策略來更新。
最初我們設計了兩套方案來打底運價數(shù)據(jù),兩個方案各有優(yōu)劣。方案1是先預加載所有的運價數(shù)據(jù),然后全部保存到數(shù)據(jù)庫和緩存,然后在航班查詢時通過緩存策略進行相應地更新;方案2是把運價數(shù)據(jù)根據(jù)航線查詢頻率分為熱門和冷門數(shù)據(jù),然后每天凌晨對熱門數(shù)據(jù)預加載,并在航班查詢的時候對冷門數(shù)據(jù)進行更新。可以看出,方案1能保證數(shù)據(jù)的完整性和實時性,但預加載用時太長;方案2能控制預加載用時,但熱門數(shù)據(jù)的實時性會從早到晚逐漸降低。兩個方案中都需要實時更新,在考慮數(shù)據(jù)實時性的同時,還要考慮獲取數(shù)據(jù)的費用,平衡好兩者才是一個實用的方案。
綜合對比之后,我們采用了方案1,具體實現(xiàn)如下圖所示:首先是通過Job對運價數(shù)據(jù)的初始化,然后以任務消息的方式發(fā)送給MQ,MQ里的消息會被后臺服務自動消費,執(zhí)行消息隊列里的任務,把運價數(shù)據(jù)保存到數(shù)據(jù)庫和緩存。數(shù)據(jù)預加載之后,用戶在前臺查詢時,如果緩存里面沒有數(shù)據(jù),或者查到的緩存數(shù)據(jù)是過期的,系統(tǒng)會自動發(fā)一條任務消息給MQ,或者人工配置指定的航線定時更新,Job也會自動發(fā)送任務消息給MQ,前臺和后臺的消息被服務消費以實現(xiàn)數(shù)據(jù)的更新。用戶的不斷請求和后臺指定的任務,保證數(shù)據(jù)的持續(xù)更新,時間越久數(shù)據(jù)的準確性越高,用戶查詢的命中率也會越來越高。
四、緩存策略與數(shù)據(jù)一致上面說到運價數(shù)據(jù)同時存儲在數(shù)據(jù)庫和緩存,為什么有了緩存還要數(shù)據(jù)庫呢?存儲到數(shù)據(jù)庫是為了方便數(shù)據(jù)的多維查詢和管理,包括對緩存的進一步干預。數(shù)據(jù)庫查詢的功能強大,但速度慢,緩存的性能好,但從緩存里獲取的數(shù)據(jù),會有不準確的問題。怎么才能做到查詢快而且數(shù)據(jù)準呢?我們的解決方法是緩存永不失效、數(shù)據(jù)分類、自主控制更新頻率,以實現(xiàn)運價數(shù)據(jù)的又快又準。
我們根據(jù)航線查詢的頻率,將可以分成熱門數(shù)據(jù)、冷門數(shù)據(jù)和沒有數(shù)據(jù),航班多、查詢多的是熱門數(shù)據(jù),航班少、查詢少的是冷門數(shù)據(jù),查詢不到就是沒有數(shù)據(jù)。在預加載或更新運價數(shù)據(jù)時,將緩存設置為一個較長時間或永不過期,然后在前臺訪問時,不同數(shù)據(jù)類型采用不同的更新策略,具體如下:
- 熱門航線查詢,在緩存中獲取數(shù)據(jù),數(shù)據(jù)中有一個自己的緩存時間字段,然后根據(jù)這個時間來分別處理:
- 1小時之內更新的:新鮮度較高,可以直接用;
- 1-6小時之內更新的:預警n次,第n+1次命中時則異步更新運價;
- 6小時之外更新的:新鮮度太低,異步更新運價;
- 冷門航線查詢,與熱門航線一樣,只是不預加載且緩存時間稍長:
- 12個小時之內更新的:新鮮度較高,可以直接用;
- 12-48個小時之內更新的:預警n次,第n+1次命中時則異步更新運價;
- 48個小時之外更新的:新鮮度太低,異步更新運價;
- 緩存沒有數(shù)據(jù)時,直接獲取最新運價,同時更新數(shù)據(jù)庫和緩存。
以上無論是預警后更新還是直接更新,都是先把緩存中數(shù)據(jù)返回給用戶,同時異步更新數(shù)據(jù)庫和緩存。雖然有存在數(shù)據(jù)查詢不準確的概率,但被用戶再次查詢時就準確了。查詢到的數(shù)據(jù)即便不準確,在后繼的航班預訂時也會二次的驗艙驗價,運價數(shù)據(jù)和庫存數(shù)據(jù)會再次更新。用戶不斷地查詢,數(shù)據(jù)不斷地更新,查詢命中率就會越來越高,并且用的人越多情況會越好,會逐步趨近于n個9。
五、實時查詢與三段超時能靜態(tài)化的數(shù)據(jù)我們要盡量靜態(tài)化,但遠端數(shù)據(jù)的實時查詢還是必不可少。實時查詢如何做到又快又好呢,特別是多數(shù)據(jù)源、多供應商的實時查詢場景。我們的國際機票查詢就是這樣,前臺頁面點擊查詢時實時調用供應商接口,早期我們僅調用一個供應接口,產品比較單一,數(shù)據(jù)不夠豐富,后面我們引入了多供應商,產品變豐富了,也有了低價,但同時帶來了很多新問題,比如供應端接口需要20~30秒,但前端客戶只能接受8秒以內,怎么辦?提高供應數(shù)據(jù)門檻?但這不是核心競爭。還有查詢速度變慢、外部數(shù)據(jù)源不可控、數(shù)據(jù)格式多樣等問題。
對于以上問題,我們的解決辦法是三段超時,所謂三段超時,即供應端、運營端和客戶端。前端滿足客人、中間滿足運營控制策略、后端滿足供應商,三方都要滿意,這樣才能產品更豐富、價格更低、運營策略更靈活、用戶響應更及時。三段超時的時間可以根據(jù)具體場景進行配置,具體如下:
- 供應端超時:供應端是后端,是指提供數(shù)據(jù)源的一方,供應端存在的問題就是外部不可控。供應端處于數(shù)據(jù)來源的最底端,解決辦法是盡量加大供應端的超時時間限制。我們對請求供應接口的最大HTTP超時時間設置為45秒,這個值可以滿足絕大部分情況。
- 運營端超時:運營端是中間端,把供應商的數(shù)據(jù)拿過來之后,做包裝轉換、去重、政策匹配等業(yè)務處理。我們先統(tǒng)計每一個供應接口的請求時間,確認供應接口數(shù)據(jù)的質量和優(yōu)先級,比如說:A供應數(shù)據(jù)的質量相比B和C供應數(shù)據(jù)的質量要高,那么A的請求級別可以設置得高一些。我們優(yōu)先考慮拿到A供應的數(shù)據(jù),如果A的數(shù)據(jù)在8秒就返回,而B和C的超過這個時間,那么我們此時在前臺就只把A的數(shù)據(jù)返回給客戶。對于B和C的數(shù)據(jù),由于在HTTP請求時我們采用異步并設置了較大的供應端超時,所以它會在A返回之后,繼續(xù)異步請求并將返回的數(shù)據(jù)保存到緩存中,以供用戶下次或其他用戶使用。當我們拿到了多供應商的產品數(shù)據(jù)后,這時會有一定重復的數(shù)據(jù),需要規(guī)范化處理,將不同數(shù)據(jù)格式轉換成統(tǒng)一標準,然后去重并選取最優(yōu),最后根據(jù)運營策略進行政策匹配等。
- 客戶端超時:客戶端是前端,需要處理最終展示和不同終端用戶的不同需求。客戶端采用多線程異步讀取,這樣不會影響主線程的速度,同時并發(fā)請求,提升響應速度和用戶體驗。這里指的主線程請求時間,可以理解為在前臺終端設備需要等待的時間,比如APP要求8秒鐘返回,那就設置8秒時間;如果PC端B2B白屏網頁查詢,客戶可以等待時間為25秒,那么就是設置25秒。客戶端的超時時間要大于或等于所有的運營端超時時間,例如客戶端超時是25秒,那么運營端線程A的超時可以最大為25秒,但如果線程A的絕大部分航線獲取時間是18秒,那么線程B和C的超時最好不要超過18秒,這里的用戶體驗要綜合考慮概率問題。
弄來這么多產品,不可能都提供給客人,需要根據(jù)運營規(guī)則來匹配。機票政策就是機票產品的運營控制策略,如上圖所示,包括政策類型、客戶類型、航程類型、乘客類型、航司、航班、艙位、城市、日期、返點 、定額、Office號等多種屬性。為什么有這么多屬性呢?因為機票產品的運營規(guī)則很復雜,而這種規(guī)則的復雜性,直接導致在航班查詢的時候,機票政策的匹配也很復雜的。對于這種大數(shù)據(jù)、復雜業(yè)務規(guī)則的數(shù)據(jù)處理,需要有一套專門的政策匹配算法,具體如下:
第一步是直接從數(shù)據(jù)庫查政策,在前端查詢的時候,根據(jù)查詢的條件,如出發(fā)到達城市、日期等,從數(shù)據(jù)庫中大范圍的獲取政策數(shù)據(jù),并把這些數(shù)據(jù)放到內存中。第二步在內存中對每個產品進行政策匹配即過濾,先將每一個屬性轉化為業(yè)務規(guī)則如限制城市、排除供應商、航司指定供應商等,一個屬性一個類、采用統(tǒng)一的接口,然后增加到政策過濾器中。產品與政策的匹配過程,就像水流過過濾網一樣,把最優(yōu)政策應用到產品上如調整價格。這個過程有些復雜,為此我們編寫了一套自己的政策過濾器PolicyFilter框架。第三步是按照政策返點高低進行排序。第四步是將最優(yōu)政策返回給前臺。以下是部分核心代碼的演示:
七、小結機票垂直搜索性能優(yōu)化不僅僅適合于機票行業(yè),也適合于其它垂直行業(yè),在垂直搜索引擎方面有一定的通用性,只要它存在:遠端數(shù)據(jù)獲取、靜態(tài)數(shù)據(jù)、緩存更新、規(guī)則匹配、多數(shù)據(jù)源等問題,都是類似解決方案。垂直搜索主要有四把刷子。第一把刷子是靜態(tài)數(shù)據(jù)與任務打底。第二把刷子是緩存與更新,保持數(shù)據(jù)的新鮮度,不僅要快,還要準。第三把刷子是實時查詢與三段超時,多供應商多數(shù)據(jù)源,供應商要20秒,客戶只能接受3秒,怎么辦?解決辦法是三段超時。第四刷子是政策匹配,好不容易弄來這么多產品,不可能都直接顯示給客人,需要根據(jù)運營規(guī)則進行匹配。以上,每一個具體的技術可能并不復雜,但把它們綜合起來,解決具體的實際問題,為公司為行業(yè)帶來價值,并不是件容易的事。技術的核心價值在于技術的應用,技術價值要借助技術應用和產品才能發(fā)揮出來,這比單純的技術學習要有意思得多,希望以上能應用到你具體的工作中。
?
posted on 2019-02-13 15:00 NET未來之路 閱讀(...) 評論(...) 編輯 收藏轉載于:https://www.cnblogs.com/lonelyxmas/p/10369891.html
總結
以上是生活随笔為你收集整理的机票垂直搜索引擎的性能优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到杀羊是什么意思周公解梦
- 下一篇: 做梦梦到自己牙掉了什么意思