馬蜂窩定制游搶單系統(tǒng)設(shè)計(jì)與功能核心
「定制旅行」已經(jīng)逐漸成為旅游行業(yè)「消費(fèi)升級(jí)」的一個(gè)主流模式。
隨著用戶(hù)對(duì)旅游服務(wù)的要求越來(lái)越高,對(duì)行程安排有個(gè)性化需求的消費(fèi)者來(lái)說(shuō),常規(guī)的跟團(tuán)游和自由行產(chǎn)品已經(jīng)很難滿(mǎn)足他們的需求。在這樣的環(huán)境下,馬蜂窩電商業(yè)務(wù)平臺(tái)也在不斷探索在提供門(mén)票、機(jī)票、酒店等這樣旅游電商「標(biāo)品」之外,如何充分結(jié)合現(xiàn)有的供應(yīng)商、旅行定制師資源優(yōu)勢(shì),更好得滿(mǎn)足用戶(hù)需求,創(chuàng)造多樣化服務(wù)。
2018 年 6 月,馬蜂窩電商業(yè)務(wù)上線(xiàn)了支持多工單搶單的「定制旅行交易系統(tǒng)」(圖 1)。不同于之前電商標(biāo)品連接人和商品的屬性,定制旅行的本質(zhì)是連接人和服務(wù),將有定制旅行需求的消費(fèi)者與有承接能力的供應(yīng)商、旅行定制師實(shí)現(xiàn)更好的匹配。
圖 1—馬蜂窩定制旅行交易系統(tǒng)
搶單模式帶來(lái)的定制旅行平臺(tái)升級(jí)
通過(guò)定制旅行平臺(tái),用戶(hù)可以根據(jù)自己的定制主體(個(gè)人/企業(yè))、出發(fā)地、目的地、往返時(shí)間、人數(shù)、預(yù)算,提交個(gè)性化旅行需求,系統(tǒng)通過(guò)搶單、派單的方式將需求與有承接能力的供應(yīng)商進(jìn)行對(duì)接。
最初,定制旅行系統(tǒng)采用的是將一個(gè)需求分發(fā)給一個(gè)供應(yīng)商的一個(gè)定制師的解決方案。這樣的做法存在幾個(gè)明顯的缺陷,比如:
- 人力承接問(wèn)題:假設(shè)供應(yīng)商的控制資源出現(xiàn)飽和,需求分配之后沒(méi)有能力承接,造成需求資源的浪費(fèi);
- 資源控制問(wèn)題:當(dāng)某個(gè)目的地進(jìn)入淡季,供應(yīng)商為了降低成品,控制資源能力減弱,沒(méi)有辦法承接需求。
為此,研發(fā)團(tuán)隊(duì)首先開(kāi)發(fā)了多工單系統(tǒng),在用戶(hù)提交定制需求時(shí),根據(jù)用戶(hù)選擇服務(wù)的定制師數(shù)量,由系統(tǒng)派發(fā)給多個(gè)供應(yīng)商的多個(gè)定制師,然后在此基礎(chǔ)上進(jìn)行系統(tǒng)升級(jí),引入了搶單功能,主要用于熱門(mén)目的地有定制游需求的個(gè)人用戶(hù)。
用戶(hù)提交定制需求后,系統(tǒng)將會(huì)根據(jù)用戶(hù)特征數(shù)據(jù)和供應(yīng)商、定制師特征數(shù)據(jù)進(jìn)行算法匹配,使用戶(hù)和定制師之間進(jìn)行雙向選擇。每個(gè)定制需求最多可以支持三家供應(yīng)商的定制師搶單同時(shí)為用戶(hù)提供旅行方案,由用戶(hù)挑選最終確認(rèn)其中一個(gè)定制師的旅行方案為用戶(hù)服務(wù)。搶單系統(tǒng)帶來(lái)的幾個(gè)好處是:
- 提升商家的積極性,通過(guò)競(jìng)爭(zhēng),提升商家的跟進(jìn)速度和轉(zhuǎn)化率
- 解放 BD 的大量工作量,取得更好的商家運(yùn)營(yíng)和轉(zhuǎn)化的結(jié)果
- 提升平臺(tái)整體轉(zhuǎn)化率,將需求在馬蜂窩平臺(tái)釋放給長(zhǎng)尾商家機(jī)會(huì),解決長(zhǎng)尾商家無(wú)法從商品排序上獲取流量的問(wèn)題,從而達(dá)到培養(yǎng)、發(fā)掘潛力商家的效果
- 供應(yīng)商主動(dòng)選擇需求單,可優(yōu)先選擇自己擅長(zhǎng)有優(yōu)勢(shì)的需求單,提升轉(zhuǎn)化率
圖2-多工單系統(tǒng)改造
搶單系統(tǒng)的關(guān)鍵是高效的資源匹配和信息溝通。因此,搶單系統(tǒng)的核心設(shè)計(jì)主要有兩點(diǎn),一是搶單池的消息隊(duì)列,如何滿(mǎn)足并發(fā)需求;二是消息通知服務(wù),如何及時(shí)有效地通知定制師。
核心技術(shù)實(shí)現(xiàn)
并發(fā)控制
搶單功能允許同一需求被多個(gè)供應(yīng)商的多個(gè)定制師同時(shí)搶到。用戶(hù)提交需求后,會(huì)進(jìn)入統(tǒng)一的搶單消息隊(duì)列。每個(gè)需求最多會(huì)有三個(gè)定制師同時(shí)為用戶(hù)提供服務(wù);在同一企業(yè)內(nèi),只有一個(gè)定制師可以搶單。
在降低并發(fā)方面,主要是通過(guò)以下兩點(diǎn)來(lái)實(shí)現(xiàn):
1. 定制師分級(jí),使用馬蜂窩消息總線(xiàn)延遲消息服務(wù),按照等級(jí)延遲通知
根據(jù)供應(yīng)商和定制師的業(yè)務(wù)范圍,BD、運(yùn)營(yíng)根據(jù)定制師的服務(wù)能力對(duì)定制師進(jìn)行定期考核劃分等級(jí),不同的定制師通過(guò)商家后臺(tái)或者微信公眾號(hào)可以看到不同的搶單池隊(duì)列。
通過(guò)使用電商自研的消息總線(xiàn)服務(wù),根據(jù)定制師服務(wù)范圍異步分發(fā),同時(shí)利用等級(jí)信息過(guò)濾搶單池隊(duì)列,保障所有的相同等級(jí)的定制師在同一時(shí)刻看到相同的搶單池隊(duì)列。
2. 控制并發(fā)鎖粒度及鎖釋放,防止死鎖
搶單接口調(diào)用時(shí)進(jìn)行十余種業(yè)務(wù)防刷控制,搶單分配時(shí),將死鎖放置到可控最細(xì)粒度,保障并發(fā)度,搶單結(jié)束后,通過(guò)長(zhǎng)連接自動(dòng)更新?lián)寙纬?,將該已搶需求從搶單池移除,避免過(guò)度打擾用戶(hù),同時(shí)減少定制師之間競(jìng)爭(zhēng)造成的資源浪費(fèi)。
定制旅行交易系統(tǒng)使用 Ko 框架,關(guān)于控制并發(fā)是采用文件鎖還是 Redis 鎖的問(wèn)題,主要是考慮:
- 文件鎖 Ko_Tool_Lock.php 不存在 expire 自動(dòng)釋放鎖的機(jī)制,如果獲得鎖未能正常釋放會(huì)死鎖。
- Ko 的 $oRedis->bSetNX 加鎖,可以設(shè)置 expire 但是問(wèn)題是不支持 setNx 同時(shí)設(shè)置 ex(拆成 2 步,不是原子操作),性能測(cè)試搶單并發(fā)度較高,對(duì)于鎖超時(shí)的偶發(fā)情況,系統(tǒng)可以回收資源進(jìn)行再次分配,因此對(duì)于發(fā)起搶單請(qǐng)求的定制師,可以首先檢查是否有超時(shí)未釋放的鎖,如果存在,則強(qiáng)制釋放鎖,然后再次嘗試獲得鎖。
圖3-鎖的控制
消息通知-長(zhǎng)連接
據(jù)統(tǒng)計(jì),定制師聯(lián)系用戶(hù)需求越及時(shí),需求轉(zhuǎn)化率越高,及時(shí)獲得搶單消息通知至關(guān)重要。消息通知的方式主要有兩種:PC 端消息彈窗,以及在移動(dòng)端通過(guò)微信公眾號(hào)的模板消息來(lái)實(shí)現(xiàn)。
為了實(shí)現(xiàn)有搶單池變更可以***時(shí)間提醒定制師,讓定制師不用自己刷新?lián)寙纬鼐涂梢詫?shí)時(shí)看到***的待搶需求,這里引入了長(zhǎng)連接服務(wù)的解決方案,并進(jìn)行了以下應(yīng)用層優(yōu)化:
1. 長(zhǎng)連接復(fù)用
定制師在查看商家后臺(tái)時(shí),會(huì)打開(kāi)多個(gè)頁(yè)面,系統(tǒng)需要在當(dāng)前的活躍頁(yè)面上進(jìn)行通知。理論上來(lái)講,每個(gè)窗口理論上都需要提供一個(gè)長(zhǎng)鏈接的服務(wù)。但這樣無(wú)疑上會(huì)造成長(zhǎng)鏈接的資源浪費(fèi)。使用“長(zhǎng)連接復(fù)用”的方式可以解決這個(gè)問(wèn)題:
(1)同一個(gè)瀏覽器多個(gè)tab頁(yè)之間共用一個(gè)長(zhǎng)連接ID(setcookie),重啟瀏覽器新建conn id
(2)同一個(gè)瀏覽器,來(lái)回切換用戶(hù),一個(gè)用戶(hù)只產(chǎn)生一次長(zhǎng)連接ID(redis hash)
2. 消息廣播
同一個(gè)瀏覽器多個(gè) tab 頁(yè)復(fù)用 conn id,互相廣播,對(duì)于活躍窗口如果出現(xiàn)沒(méi)有監(jiān)聽(tīng)的消息,廣播到活躍窗口上去。
圖4-搶單系統(tǒng)消息通知與廣播
3. 重試機(jī)制
網(wǎng)絡(luò)異常是不可避免的,我們不知道什么時(shí)候網(wǎng)絡(luò)會(huì)斷,導(dǎo)致長(zhǎng)連接斷掉,會(huì)對(duì)消息通知帶來(lái)影響。采用重試機(jī)制,限定時(shí)間周期,監(jiān)聽(tīng)網(wǎng)絡(luò)有沒(méi)有異常。在長(zhǎng)連接斷開(kāi)時(shí)指定短時(shí)間內(nèi)自動(dòng)重試,超過(guò)最多重試次數(shù)后,自動(dòng)延長(zhǎng)重試間隔,防止服務(wù)異常雪崩問(wèn)題。
圖5-重試機(jī)制
4. Lua 協(xié)程
最初長(zhǎng)連接請(qǐng)求打到服務(wù)器之后,服務(wù)器的承接方式是通過(guò) PHP 進(jìn)程。項(xiàng)目上線(xiàn)后發(fā)現(xiàn)了一個(gè)問(wèn)題,服務(wù)器上的請(qǐng)求長(zhǎng)時(shí)間掛在一個(gè)比較高的點(diǎn)上,可以處理的長(zhǎng)連接需求受限。而且特點(diǎn)是內(nèi)存比較大,但 CPU 消耗比較小。后來(lái)我們采用了 Lua 協(xié)程的解決方案,不是把請(qǐng)求轉(zhuǎn)到 PHP FPM 上,而是轉(zhuǎn)接到 Lua 上,減少內(nèi)存的消耗。
小結(jié)與未來(lái)規(guī)劃
定制搶單功能的上線(xiàn)促進(jìn)了供應(yīng)商之間的良性競(jìng)爭(zhēng),能夠適應(yīng)供應(yīng)商服務(wù)能力和資源控制力多樣性而進(jìn)行動(dòng)態(tài)分配,確保用戶(hù)的需求得到充分滿(mǎn)足,另外,也在一定程度上促進(jìn)了供應(yīng)商內(nèi)部的定制師考核制度不斷完善。更重要的是,使定制游平臺(tái)上的收益轉(zhuǎn)化率有了超過(guò) 70% 的明顯提升。
本文作者:王偉陽(yáng),馬蜂窩技術(shù)專(zhuān)家,2017 年加入馬蜂窩,現(xiàn)負(fù)責(zé)馬蜂窩電商度假業(yè)務(wù)開(kāi)發(fā)。2010 年研究生畢業(yè)于中國(guó)農(nóng)業(yè)大學(xué),曾在甲骨文、百度工作,先后從事分布式拓?fù)洵h(huán)境任務(wù)調(diào)度與報(bào)告系統(tǒng),工程效率與質(zhì)量平臺(tái)與工具,評(píng)估測(cè)評(píng)系統(tǒng)等方向的研發(fā)工作。
【本文是51CTO專(zhuān)欄作者馬蜂窩技術(shù)的原創(chuàng)文章,作者微信公眾號(hào)馬蜂窩技術(shù)(ID:mfwtech)】