「定製旅行」已經逐漸成爲旅遊行業「消費升級」的一個主流模式。php
隨着用戶對旅遊服務的要求愈來愈高,對行程安排有個性化需求的消費者來講,常規的跟團遊和自由行產品已經很難知足他們的需求。在這樣的環境下,馬蜂窩電商業務平臺也在不斷探索在提供門票、機票、酒店等這樣旅遊電商「標品」以外,如何充分結合現有的供應商、旅行定製師資源優點,更好得知足用戶需求,創造多樣化服務。redis
2018 年 6 月,馬蜂窩電商業務上線了支持多工單搶單的「定製旅行交易系統」(圖 1)。不一樣於以前電商標品鏈接人和商品的屬性,定製旅行的本質是鏈接人和服務,將有定製旅行需求的消費者與有承接能力的供應商、旅行定製師實現更好的匹配。算法
圖 1—馬蜂窩定製旅行交易系統瀏覽器
經過定製旅行平臺,用戶能夠根據本身的定製主體(我的/企業)、出發地、目的地、往返時間、人數、預算,提交個性化旅行需求,系統經過搶單、派單的方式將需求與有承接能力的供應商進行對接。服務器
最初,定製旅行系統採用的是將一個需求分發給一個供應商的一個定製師的解決方案。這樣的作法存在幾個明顯的缺陷,好比:微信
人力承接問題:假設供應商的控制資源出現飽和,需求分配以後沒有能力承接,形成需求資源的浪費;cookie
資源控制問題:當某個目的地進入淡季,供應商爲了下降成品,控制資源能力減弱,沒有辦法承接需求。網絡
爲此,研發團隊首先開發了多工單系統,在用戶提交定製需求時,根據用戶選擇服務的定製師數量,由系統派發給多個供應商的多個定製師,而後在此基礎上進行系統升級,引入了搶單功能,主要用於熱門目的地有定製遊需求的我的用戶。併發
用戶提交定製需求後,系統將會根據用戶特徵數據和供應商、定製師特徵數據進行算法匹配,使用戶和定製師之間進行雙向選擇。每一個定製需求最多能夠支持三家供應商的定製師搶單同時爲用戶提供旅行方案,由用戶挑選最終確認其中一個定製師的旅行方案爲用戶服務。搶單系統帶來的幾個好處是:框架
提高商家的積極性,經過競爭,提高商家的跟進速度和轉化率
解放 BD 的大量工做量,取得更好的商家運營和轉化的結果
提高平臺總體轉化率,將需求在馬蜂窩平臺釋放給長尾商家機會,解決長尾商家沒法從商品排序上獲取流量的問題,從而達到培養、發掘潛力商家的效果
供應商主動選擇需求單,可優先選擇本身擅長有優點的需求單,提高轉化率
圖2-多工單系統改造
搶單系統的關鍵是高效的資源匹配和信息溝通。所以,搶單系統的核心設計主要有兩點,一是搶單池的消息隊列,如何知足併發需求;二是消息通知服務,如何及時有效地通知定製師。
搶單功能容許同一需求被多個供應商的多個定製師同時搶到。用戶提交需求後,會進入統一的搶單消息隊列。每一個需求最多會有三個定製師同時爲用戶提供服務;在同一企業內,只有一個定製師能夠搶單。
在下降併發方面,主要是經過如下兩點來實現:
根據供應商和定製師的業務範圍,BD、運營根據定製師的服務能力對定製師進行按期考覈劃分等級,不一樣的定製師經過商家後臺或者微信公衆號能夠看到不一樣的搶單池隊列。
經過使用電商自研的消息總線服務,根據定製師服務範圍異步分發,同時利用等級信息過濾搶單池隊列,保障全部的相同等級的定製師在同一時刻看到相同的搶單池隊列。
搶單接口調用時進行十餘種業務防刷控制,搶單分配時,將死鎖放置到可控最細粒度,保障併發度,搶單結束後,經過長鏈接自動更新搶單池,將該已搶需求從搶單池移除,避免過分打擾用戶,同時減小定製師之間競爭形成的資源浪費。
定製旅行交易系統使用 Ko 框架,關於控制併發是採用文件鎖仍是 Redis 鎖的問題,主要是考慮:
文件鎖 Ko_Tool_Lock.php 不存在 expire 自動釋放鎖的機制,若是得到鎖未能正常釋放會死鎖。
Ko 的 $oRedis->bSetNX 加鎖,能夠設置 expire 可是問題是不支持 setNx 同時設置 ex(拆成 2 步,不是原子操做),性能測試搶單併發度較高,對於鎖超時的偶發狀況,系統能夠回收資源進行再次分配,所以對於發起搶單請求的定製師,能夠首先檢查是否有超時未釋放的鎖,若是存在,則強制釋放鎖,而後再次嘗試得到鎖。
圖3-鎖的控制
據統計,定製師聯繫用戶需求越及時,需求轉化率越高,及時得到搶單消息通知相當重要。消息通知的方式主要有兩種:PC 端消息彈窗,以及在移動端經過微信公衆號的模板消息來實現。
爲了實現有搶單池變動能夠第一時間提醒定製師,讓定製師不用本身刷新搶單池就能夠實時看到最新的待搶需求,這裏引入了長鏈接服務的解決方案,並進行了如下應用層優化:
定製師在查看商家後臺時,會打開多個頁面,系統須要在當前的活躍頁面上進行通知。理論上來說,每一個窗口理論上都須要提供一個長連接的服務。但這樣無疑上會形成長連接的資源浪費。使用「長鏈接複用」的方式能夠解決這個問題:
(1)同一個瀏覽器多個tab頁之間共用一個長鏈接ID(setcookie),重啓瀏覽器新建conn id
(2)同一個瀏覽器,來回切換用戶,一個用戶只產生一次長鏈接ID(redis hash)
同一個瀏覽器多個 tab 頁複用 conn id,互相廣播,對於活躍窗口若是出現沒有監聽的消息,廣播到活躍窗口上去。
圖4-搶單系統消息通知與廣播
網絡異常是不可避免的,咱們不知道何時網絡會斷,致使長鏈接斷掉,會對消息通知帶來影響。採用重試機制,限定時間週期,監聽網絡有沒有異常。在長鏈接斷開時指定短期內自動重試,超過最多重試次數後,自動延長重試間隔,防止服務異常雪崩問題。
圖5-重試機制
最初長鏈接請求打到服務器以後,服務器的承接方式是經過 PHP 進程。項目上線後發現了一個問題,服務器上的請求長時間掛在一個比較高的點上,能夠處理的長鏈接需求受限。並且特色是內存比較大,但 CPU 消耗比較小。後來咱們採用了 Lua 協程的解決方案,不是把請求轉到 PHP FPM 上,而是轉接到 Lua 上,減小內存的消耗。
定製搶單功能的上線促進了供應商之間的良性競爭,可以適應供應商服務能力和資源控制力多樣性而進行動態分配,確保用戶的需求獲得充分知足,另外,也在必定程度上促進了供應商內部的定製師考覈制度不斷完善。更重要的是,使定製遊平臺上的收益轉化率有了超過 70% 的明顯提高。
將來,定製旅行平臺會不斷完善系統功能,好比在搶單模型的擴展、搶單定製師評級自動反饋調節閉環建設等方面,但願和你們交流,歡迎多提寶貴意見。您能夠掃描下方二維碼訂閱「馬蜂窩技術」更多內容。
本文做者:王偉陽,馬蜂窩技術專家。
微信關注「馬蜂窩技術」公衆號,閱讀更多技術乾貨。