vivo?億級(jí)優(yōu)惠券系統(tǒng)架構(gòu)設(shè)計(jì)與實(shí)踐
作者:vivo互聯(lián)網(wǎng)開(kāi)發(fā)團(tuán)隊(duì)-Yan Chao
一、業(yè)務(wù)背景
優(yōu)惠券是電商常見(jiàn)的營(yíng)銷(xiāo)手段,具有靈活的特點(diǎn),既可以作為促銷(xiāo)活動(dòng)的載體,也是重要的引流入口。優(yōu)惠券系統(tǒng)是vivo商城營(yíng)銷(xiāo)模塊中一個(gè)重要組成部分,早在15年vivo商城還是單體應(yīng)用時(shí),優(yōu)惠券就是其中核心模塊之一。隨著商城的發(fā)展及用戶(hù)量的提升,優(yōu)惠券做了服務(wù)拆分,成立了獨(dú)立的優(yōu)惠券系統(tǒng),提供通用的優(yōu)惠券服務(wù)。目前,優(yōu)惠券系統(tǒng)覆蓋了優(yōu)惠券的4個(gè)核心要點(diǎn):創(chuàng)、發(fā)、用、計(jì)。
- “創(chuàng)”指優(yōu)惠券的創(chuàng)建,包含各種券規(guī)則和使用門(mén)檻的配置。
- “發(fā)”指優(yōu)惠券的發(fā)放,優(yōu)惠券系統(tǒng)提供了多種發(fā)放優(yōu)惠券的方式,滿(mǎn)足針對(duì)不同人群的主動(dòng)發(fā)放和被動(dòng)發(fā)放。
- “用”指優(yōu)惠券的使用,包括正向購(gòu)買(mǎi)商品及反向退款后的優(yōu)惠券回退。
- “計(jì)”指優(yōu)惠券的統(tǒng)計(jì),包括優(yōu)惠券的發(fā)放數(shù)量、使用數(shù)量、使用商品等數(shù)據(jù)匯總。
vivo商城優(yōu)惠券系統(tǒng)除了提供常見(jiàn)的優(yōu)惠券促銷(xiāo)玩法外,還以?xún)?yōu)惠券的形式作為其他一些活動(dòng)或資產(chǎn)的載體,比如手機(jī)類(lèi)商品的保值換新、內(nèi)購(gòu)福利、與外部廣告商合作發(fā)放優(yōu)惠券等。
以下為vivo商城優(yōu)惠券部分場(chǎng)景的展示:

二、系統(tǒng)架構(gòu)及變遷
優(yōu)惠券最早和商城耦合在一個(gè)系統(tǒng)中。隨著vivo商城的不斷發(fā)展,營(yíng)銷(xiāo)活動(dòng)力度加大,優(yōu)惠券使用場(chǎng)景增多,優(yōu)惠券系統(tǒng)逐漸開(kāi)始“力不從心”,暴露了很多問(wèn)題:
- 海量?jī)?yōu)惠券的發(fā)放,達(dá)到優(yōu)惠券單庫(kù)、單表存儲(chǔ)瓶頸。
- 與商城系統(tǒng)的高耦合,直接影響了商城整站接口性能。
- 優(yōu)惠券的迭代更新受限于商城的版本安排。
- 針對(duì)多品類(lèi)優(yōu)惠券,技術(shù)層面沒(méi)有沉淀通用優(yōu)惠券能力。
為了解決以上問(wèn)題,19年優(yōu)惠券系統(tǒng)進(jìn)行了系統(tǒng)獨(dú)立,提供通用的優(yōu)惠券服務(wù),獨(dú)立后的系統(tǒng)架構(gòu)如下:

優(yōu)惠券系統(tǒng)獨(dú)立遷移方案如何將優(yōu)惠券從商城系統(tǒng)遷移出來(lái),并兼容已對(duì)接的業(yè)務(wù)方和歷史數(shù)據(jù),也是一大技術(shù)挑戰(zhàn)。系統(tǒng)遷移有兩種方案:停機(jī)遷移和不停機(jī)遷移。
我們采用的是不停機(jī)遷移方案:
- 遷移前,運(yùn)營(yíng)停止與優(yōu)惠券相關(guān)的后臺(tái)操作,避免產(chǎn)生優(yōu)惠券靜態(tài)數(shù)據(jù)。
靜態(tài)數(shù)據(jù):優(yōu)惠券后臺(tái)生成的數(shù)據(jù),與用戶(hù)無(wú)關(guān)。動(dòng)態(tài)數(shù)據(jù):與用戶(hù)有關(guān)的優(yōu)惠券數(shù)據(jù),含用戶(hù)領(lǐng)取的券、券和訂單的關(guān)系數(shù)據(jù)等。
- 配置當(dāng)前數(shù)據(jù)庫(kù)開(kāi)關(guān)為單寫(xiě),即優(yōu)惠券數(shù)據(jù)寫(xiě)入商城庫(kù)(舊庫(kù))。
- 優(yōu)惠券系統(tǒng)上線(xiàn),通過(guò)腳本遷移靜態(tài)數(shù)據(jù)。遷完后,驗(yàn)證靜態(tài)數(shù)據(jù)遷移準(zhǔn)確性。
- 配置當(dāng)前數(shù)據(jù)庫(kù)開(kāi)關(guān)為雙寫(xiě),即線(xiàn)上數(shù)據(jù)同時(shí)寫(xiě)入商城庫(kù)和優(yōu)惠券新庫(kù)。此時(shí)服務(wù)提供的數(shù)據(jù)源依舊是商城庫(kù)。
- 遷移動(dòng)態(tài)數(shù)據(jù)。遷完后,驗(yàn)證動(dòng)態(tài)數(shù)據(jù)遷移準(zhǔn)確性。
- 切換數(shù)據(jù)源,服務(wù)提供的數(shù)據(jù)源切換到新庫(kù)。驗(yàn)證服務(wù)是否正確,出現(xiàn)問(wèn)題時(shí),切換回商城數(shù)據(jù)源。
- 關(guān)閉雙寫(xiě),優(yōu)惠券系統(tǒng)遷移完成。
遷移后優(yōu)惠券系統(tǒng)請(qǐng)求拓?fù)鋱D如下:

三、系統(tǒng)設(shè)計(jì)
3.1 優(yōu)惠券分庫(kù)分表
隨著優(yōu)惠券發(fā)放量越來(lái)越大,單表已經(jīng)達(dá)到瓶頸。為了支撐業(yè)務(wù)的發(fā)展,綜合考慮,對(duì)用戶(hù)優(yōu)惠券數(shù)據(jù)進(jìn)行分庫(kù)分表。
關(guān)鍵字:技術(shù)選型、分庫(kù)分表因子
分庫(kù)分表有成熟的開(kāi)源方案,這里不做過(guò)多介紹。參考之前項(xiàng)目經(jīng)驗(yàn),采用了公司中間件團(tuán)隊(duì)提供的自研框架。原理是引入自研的MyBatis的插件,根據(jù)自定義的路由策略計(jì)算不同的庫(kù)表后綴,定位至相應(yīng)的庫(kù)表。
用戶(hù)優(yōu)惠券與用戶(hù)id關(guān)聯(lián),并且用戶(hù)id是貫穿整個(gè)系統(tǒng)的重要字段,因此使用用戶(hù)id作為分庫(kù)分表的路由因子。這樣可以保證同一個(gè)用戶(hù)路由至相同的庫(kù)表,既有利于數(shù)據(jù)的聚合,也方便用戶(hù)數(shù)據(jù)的查詢(xún)。
假設(shè)共分N個(gè)庫(kù)M個(gè)表,分庫(kù)分表的路由策略為:
庫(kù)后綴databaseSuffix = hash(userId) / M %N表后綴tableSuffix = hash(userId) % M

3.2 優(yōu)惠券發(fā)放方式設(shè)計(jì)
為滿(mǎn)足各種不同場(chǎng)景的發(fā)券需求,優(yōu)惠券系統(tǒng)提供三種發(fā)券方式:統(tǒng)一領(lǐng)券接口、后臺(tái)定向發(fā)券、券碼兌換發(fā)放。
3.2.1 統(tǒng)一領(lǐng)券接口
保證領(lǐng)券校驗(yàn)的準(zhǔn)確性領(lǐng)券時(shí),需要嚴(yán)格校驗(yàn)優(yōu)惠券的各種屬性是否滿(mǎn)足:比如領(lǐng)取對(duì)象、各種限制條件等。其中,比較關(guān)鍵的是庫(kù)存和領(lǐng)取數(shù)量的校驗(yàn)。因?yàn)樵诟卟l(fā)的情況下,需保證數(shù)量校驗(yàn)的準(zhǔn)確性,不然很容易造成用戶(hù)超領(lǐng)。
存在這樣的場(chǎng)景:A用戶(hù)連續(xù)發(fā)起兩次領(lǐng)取券C的請(qǐng)求,券C限制每個(gè)用戶(hù)領(lǐng)取一張。第一次請(qǐng)求通過(guò)了領(lǐng)券數(shù)量的校驗(yàn),在用戶(hù)優(yōu)惠券未落庫(kù)的情況下,如果不做限制,第二次請(qǐng)求也會(huì)通過(guò)領(lǐng)券數(shù)量的校驗(yàn)。這樣A用戶(hù)會(huì)成功領(lǐng)取兩張券C,造成超領(lǐng)。
為了解決這個(gè)問(wèn)題,優(yōu)惠券采用的是分布式鎖方案,分布式鎖的實(shí)現(xiàn)依賴(lài)于Redis。在校驗(yàn)用戶(hù)領(lǐng)券數(shù)量前先嘗試獲取分布式鎖,優(yōu)惠券發(fā)放成功后釋放鎖,保證用戶(hù)領(lǐng)取同一張券時(shí)不會(huì)出現(xiàn)超領(lǐng)。上面這種場(chǎng)景,用戶(hù)第一次請(qǐng)求成功獲取分布式鎖后,直至第一次請(qǐng)求成功釋放已獲取的分布式鎖或超時(shí)釋放,不然用戶(hù)第二次請(qǐng)求會(huì)獲取分布式鎖失敗,這樣保證A用戶(hù)只會(huì)成功領(lǐng)取一張。
庫(kù)存扣減領(lǐng)券要進(jìn)行庫(kù)存扣減,常見(jiàn)庫(kù)存扣減方案有兩種:
方案一:數(shù)據(jù)庫(kù)扣減??蹨p庫(kù)存時(shí),直接更新數(shù)據(jù)庫(kù)中庫(kù)存字段。
該方案的優(yōu)點(diǎn)是簡(jiǎn)單便捷,查驗(yàn)庫(kù)存時(shí)直接查庫(kù)即可獲取到實(shí)時(shí)庫(kù)存。且有數(shù)據(jù)庫(kù)事務(wù)保證,不用考慮數(shù)據(jù)丟失和不一致的問(wèn)題。
缺點(diǎn)也很明顯,主要有兩點(diǎn):1)庫(kù)存是數(shù)據(jù)庫(kù)中的單個(gè)字段,在更新庫(kù)存時(shí),所有的請(qǐng)求需要等待行鎖。一旦并發(fā)量大了,就會(huì)有很多請(qǐng)求阻塞在這里,導(dǎo)致請(qǐng)求超時(shí),進(jìn)而系統(tǒng)雪崩。2)頻繁請(qǐng)求數(shù)據(jù)庫(kù),比較耗時(shí),且會(huì)大量占用數(shù)據(jù)庫(kù)連接資源。
方案二:基于redis實(shí)現(xiàn)庫(kù)存扣減操作。將庫(kù)存放到緩存中,利用redis的incrby特性來(lái)扣減庫(kù)存。
該方案的優(yōu)點(diǎn)是突破數(shù)據(jù)庫(kù)的瓶頸,速度快,性能高。
缺點(diǎn)是系統(tǒng)流程會(huì)比較復(fù)雜,而且需要考慮緩存丟失或宕機(jī)數(shù)據(jù)恢復(fù)的問(wèn)題,容易造成庫(kù)存數(shù)據(jù)不一致。
從優(yōu)惠券系統(tǒng)當(dāng)前及可預(yù)見(jiàn)未來(lái)的流量峰值、系統(tǒng)維護(hù)性、實(shí)用性上綜合考慮,優(yōu)惠券系統(tǒng)采用了方案一的改進(jìn)方案。改進(jìn)方案是將單庫(kù)存字段分散成多庫(kù)存字段,分散數(shù)據(jù)庫(kù)的行鎖,減少并發(fā)量大的情況數(shù)據(jù)庫(kù)的行鎖瓶頸。

庫(kù)存數(shù)更新后,會(huì)將庫(kù)存平均分配成M份,初始化更新到庫(kù)存記錄表中。用戶(hù)領(lǐng)券,隨機(jī)選取庫(kù)存記錄表中已分配的某一庫(kù)存字段(共M個(gè))進(jìn)行更新,更新成功即為庫(kù)存扣減成功。同時(shí),定時(shí)任務(wù)會(huì)定期同步已領(lǐng)取的庫(kù)存數(shù)。相比方案一,該方案突破了數(shù)據(jù)庫(kù)單行鎖的瓶頸限制,且實(shí)現(xiàn)簡(jiǎn)單,不用考慮數(shù)據(jù)丟失和不一致的問(wèn)題。
一鍵領(lǐng)取多張券在對(duì)接的業(yè)務(wù)方的領(lǐng)券場(chǎng)景中,存在用戶(hù)一鍵領(lǐng)取多張券的情形。因此統(tǒng)一領(lǐng)券接口需要支持用戶(hù)一鍵領(lǐng)券,除了領(lǐng)取同一券模板的多張,也支持領(lǐng)取不同券模板的多張。一般來(lái)說(shuō),一鍵領(lǐng)取多張券指領(lǐng)取不同券模板的多張。在實(shí)現(xiàn)過(guò)程中,需要注意以下幾點(diǎn):
1)如何保證性能領(lǐng)取多張券,如果每張券分別進(jìn)行校驗(yàn)、庫(kù)存扣減、入庫(kù),那么接口性能的瓶頸卡在券的數(shù)量上,數(shù)量越多,性能直線(xiàn)下降。那么在券數(shù)量多的情況下,怎么保證高性能呢?主要采取兩個(gè)措施:
a. 批量操作。從發(fā)券流程來(lái)看,瓶頸在于券的入庫(kù)。領(lǐng)券是實(shí)時(shí)的(異步的話(huà),不能實(shí)時(shí)將券發(fā)到用戶(hù)賬戶(hù)下,影響到用戶(hù)的體驗(yàn)還有券的轉(zhuǎn)化率),券越多,入庫(kù)時(shí)與數(shù)據(jù)庫(kù)的IO次數(shù)越多,性能越差。批量入庫(kù)可以保證與數(shù)據(jù)庫(kù)的IO的次數(shù)只有一次,不受券的數(shù)量影響。如上所述,用戶(hù)優(yōu)惠券數(shù)據(jù)做了分庫(kù)分表,同一用戶(hù)的優(yōu)惠券資產(chǎn)保存在同一庫(kù)表中,因此同一用戶(hù)可實(shí)現(xiàn)批量入庫(kù)。
b. 限制單次領(lǐng)券數(shù)量。設(shè)置閥值,超出數(shù)量后,直接返回,保證系統(tǒng)在安全范圍內(nèi)。
2)保證高并發(fā)情況下,用戶(hù)不會(huì)超領(lǐng)假如用戶(hù)在商城發(fā)起請(qǐng)求,一鍵領(lǐng)取A/B/C/D四張券,同時(shí)活動(dòng)系統(tǒng)給用戶(hù)發(fā)放券A,這兩個(gè)領(lǐng)券請(qǐng)求是同時(shí)的。其中,券A限制了每個(gè)用戶(hù)只能領(lǐng)取一張。按照前述采用分布式鎖保證校驗(yàn)的準(zhǔn)確性,兩次請(qǐng)求的分布式鎖的key分別為:
用戶(hù)id A_id B_id C_id D_id用戶(hù)id A_id
這種情況下,兩次請(qǐng)求的分布式鎖并沒(méi)有發(fā)揮作用,因?yàn)殒ikey是不同,數(shù)量校驗(yàn)依舊存在錯(cuò)誤的可能性。為避免批量領(lǐng)券過(guò)程中用戶(hù)超領(lǐng)現(xiàn)象的發(fā)生,在批量領(lǐng)券過(guò)程中,對(duì)分布鎖的獲取進(jìn)行了改造。上例一鍵領(lǐng)取A/B/C/D四張券,需要批量獲取4個(gè)分布式鎖,鎖key為:
用戶(hù)id A_id用戶(hù)id B_id用戶(hù)id C_id用戶(hù)id D_id
獲取其中任何一個(gè)鎖失敗,即表明此時(shí)該用戶(hù)正在領(lǐng)取其中某一張券,需要自旋等待(在超時(shí)時(shí)間內(nèi))。獲取所有的分布式鎖成功,才可以進(jìn)行下一步。
接口冪等性統(tǒng)一領(lǐng)券接口需保證冪等性(冪等性:用戶(hù)對(duì)于同一操作發(fā)起的一次請(qǐng)求或者多次請(qǐng)求的結(jié)果是一致的)。在網(wǎng)絡(luò)超時(shí)、異常情況下,領(lǐng)券結(jié)果沒(méi)有及時(shí)返回,業(yè)務(wù)方會(huì)進(jìn)行領(lǐng)券重試。如果接口不保證冪等性,會(huì)造成超發(fā)。冪等性的實(shí)現(xiàn)有多種方案,優(yōu)惠券系統(tǒng)利用數(shù)據(jù)庫(kù)的唯一索引來(lái)保證冪等。
領(lǐng)券最早是不支持冪等性的,表設(shè)計(jì)沒(méi)有考慮冪等性。
那么第一個(gè)需要考慮的問(wèn)題:在哪個(gè)表來(lái)添加唯一索引呢?
無(wú)非兩種方案:現(xiàn)有的表或者新建表。
- 采用現(xiàn)有的表,不需要增加表的關(guān)聯(lián)。但如上所述,因?yàn)樽隽朔謳?kù)分表,大量的表需要添加唯一字段,并且需要兼容歷史數(shù)據(jù),需要保證歷史數(shù)據(jù)新增字段的唯一性。
- 采用新建表這種方式,不需要兼容歷史數(shù)據(jù),但缺陷也很明顯,增加了一層表的關(guān)聯(lián),對(duì)性能和現(xiàn)有邏輯都有很大影響。綜合考慮,我們選取了在現(xiàn)有表添加唯一字段這種方式,這樣更利于保證性能和后續(xù)的維護(hù)性。
第二個(gè)考慮的問(wèn)題:怎么兼容歷史數(shù)據(jù)和業(yè)務(wù)方?歷史數(shù)據(jù)增加了唯一字段,需要填入唯一值,不然無(wú)法添加唯一索引。我們采用腳本刷數(shù)據(jù)的方式,構(gòu)造唯一值并刷新到每一行歷史數(shù)據(jù)中。優(yōu)惠券已對(duì)接的業(yè)務(wù)方?jīng)]有傳入唯一編碼,針對(duì)這種情況,優(yōu)惠券側(cè)生成唯一編碼作為替代,保證兼容性。
3.2.2 定向發(fā)券
定向發(fā)券用于運(yùn)營(yíng)在后臺(tái)針對(duì)特定人群進(jìn)行發(fā)券。定向發(fā)券可以彌補(bǔ)用戶(hù)主動(dòng)領(lǐng)券,人群覆蓋不精準(zhǔn)、覆蓋面不廣的問(wèn)題。通過(guò)定向發(fā)券,可以精準(zhǔn)覆蓋特定人群,提高下單轉(zhuǎn)化率。在大促期間,大范圍人群的定向發(fā)券還可以承載活動(dòng)push和降價(jià)促銷(xiāo)雙重任務(wù)。
定向發(fā)券主要在于人群的圈選和發(fā)券流程的設(shè)計(jì),整體流程如下:

定向發(fā)券不同于用戶(hù)主動(dòng)領(lǐng)券,定向發(fā)券的量通常會(huì)很大(億級(jí))。為了支撐大批量的定向發(fā)券,定向發(fā)券做了一些優(yōu)化:
1)去除事務(wù)。事務(wù)邏輯過(guò)重,對(duì)于定向發(fā)券來(lái)說(shuō)沒(méi)必要。發(fā)券失敗,記錄失敗的券,保證失敗可以重試。
2)輕量化校驗(yàn)。定向發(fā)券限制了券類(lèi)型,通過(guò)限制配置的方式規(guī)避需嚴(yán)格校驗(yàn)屬性的配置。不同于用戶(hù)主動(dòng)領(lǐng)券校驗(yàn)邏輯的冗長(zhǎng),定向發(fā)券的校驗(yàn)非常輕量,大大提升發(fā)券性能。
3)批量插入。批量券插入減少數(shù)據(jù)庫(kù)IO次數(shù),消除數(shù)據(jù)庫(kù)瓶頸,提升發(fā)券速度。定向發(fā)券是針對(duì)不同的用戶(hù),用戶(hù)優(yōu)惠券做了分庫(kù)分表,為了實(shí)現(xiàn)批量插入,需要在內(nèi)存中先計(jì)算出不同用戶(hù)對(duì)應(yīng)的庫(kù)表后綴,數(shù)據(jù)歸集后再批量插入,最多插入M次,M為庫(kù)表總個(gè)數(shù)。
4)核心參數(shù)可動(dòng)態(tài)配置。比如單次發(fā)券數(shù)量,單次讀庫(kù)數(shù)量,發(fā)給消息中心的消息體包含的用戶(hù)數(shù)量等,可以控制定向發(fā)券的峰值速度和平均速度。
3.2.3 券碼兌換
站外營(yíng)銷(xiāo)券的發(fā)放方式與其他券不同,通過(guò)券碼進(jìn)行兌換。券碼由后臺(tái)導(dǎo)出,通過(guò)短信或者活動(dòng)的方式發(fā)放到用戶(hù),用戶(hù)根據(jù)券碼兌換后獲取相應(yīng)的券。券碼的組成有一定的規(guī)則,在規(guī)則的基礎(chǔ)上要保證安全性,這種安全性主要是券碼校驗(yàn)的準(zhǔn)確性,防止已兌換券碼的再次兌換和無(wú)效券碼的惡意兌換。
3.3 精細(xì)化營(yíng)銷(xiāo)能力設(shè)計(jì)
通過(guò)標(biāo)簽組合配置的方式,優(yōu)惠券提供精細(xì)化營(yíng)銷(xiāo)的能力,以實(shí)現(xiàn)優(yōu)惠券的千人千面。標(biāo)簽可分為準(zhǔn)實(shí)時(shí)和實(shí)時(shí),值得注意的是,一些實(shí)時(shí)的標(biāo)簽的處理需要前提條件,比如地區(qū)屬性需要用戶(hù)授權(quán)。
優(yōu)惠券的精準(zhǔn)觸達(dá):

3.4 券和商品之間的關(guān)系
優(yōu)惠券的使用需要和商品關(guān)聯(lián),可關(guān)聯(lián)所有商品,也可以關(guān)聯(lián)部分商品。為了靈活性地滿(mǎn)足運(yùn)營(yíng)對(duì)于券關(guān)聯(lián)商品的配置,優(yōu)惠券系統(tǒng)有兩種關(guān)聯(lián)方式:
a. 黑名單。可用商品 = 全部商品 - 黑名單商品。黑名單適用于券的可使用商品范圍比較廣這種情況,全部商品排除掉黑名單商品就是券的可使用范圍。
b. 白名單。可用商品 = 白名單商品。白名單適用于券的可使用商品范圍比較小這種情況,直接配置券的可使用商品。
除此以外,還有超級(jí)黑名單的配置,黑名單和白名單只對(duì)單個(gè)券有效,超級(jí)黑名單對(duì)所有券有效。當(dāng)前優(yōu)惠券系統(tǒng)提供商品級(jí)的關(guān)聯(lián),后續(xù)優(yōu)惠券會(huì)支持商品分類(lèi)維度的關(guān)聯(lián),分類(lèi)維度 商品維度可以更靈活地關(guān)聯(lián)優(yōu)惠券和商品。
3.5 高性能保證
優(yōu)惠券對(duì)接系統(tǒng)多,存在高流量場(chǎng)景,優(yōu)惠券對(duì)外提供接口需保證高性能和高穩(wěn)定性。
多級(jí)緩存為了提升查詢(xún)速度,減輕數(shù)據(jù)庫(kù)的壓力,同時(shí)為了應(yīng)對(duì)瞬時(shí)高流量帶來(lái)熱點(diǎn)key的場(chǎng)景(比如發(fā)布會(huì)直播結(jié)束切換流量至特定商品商詳頁(yè)、熱點(diǎn)活動(dòng)商品商詳頁(yè)都會(huì)給優(yōu)惠券系統(tǒng)帶來(lái)瞬時(shí)高流量),優(yōu)惠券采用了多級(jí)緩存的方式。

數(shù)據(jù)庫(kù)讀寫(xiě)分離優(yōu)惠券除了上述所說(shuō)的分庫(kù)分表外,在此基礎(chǔ)上還做了讀寫(xiě)分離操作。主庫(kù)負(fù)責(zé)執(zhí)行數(shù)據(jù)更新請(qǐng)求,然后將數(shù)據(jù)變更實(shí)時(shí)同步到所有從庫(kù),用從庫(kù)來(lái)分擔(dān)查詢(xún)請(qǐng)求,解決數(shù)據(jù)庫(kù)寫(xiě)入影響查詢(xún)的問(wèn)題。主從同步存在延遲,正常情況下延遲不超過(guò)1ms,優(yōu)惠券的領(lǐng)取或狀態(tài)變更存在一個(gè)耗時(shí)的過(guò)程,主從延遲對(duì)于用戶(hù)來(lái)說(shuō)無(wú)感知。

依賴(lài)外部接口隔離熔斷優(yōu)惠券內(nèi)部依賴(lài)了第三方的系統(tǒng),為了防止因?yàn)橐蕾?lài)方服務(wù)不可用,產(chǎn)生連鎖效應(yīng),最終導(dǎo)致優(yōu)惠券服務(wù)雪崩的事情發(fā)生,優(yōu)惠券對(duì)依賴(lài)外部接口做了隔離和熔斷。
用戶(hù)維度優(yōu)惠券字段冗余查詢(xún)用戶(hù)相關(guān)的優(yōu)惠券數(shù)據(jù)是優(yōu)惠券最頻繁的查詢(xún)操作之一,用戶(hù)優(yōu)惠券數(shù)據(jù)做了分庫(kù)分表,在查詢(xún)時(shí)無(wú)法關(guān)聯(lián)券規(guī)則表進(jìn)行查詢(xún),為了減少I(mǎi)O次數(shù),用戶(hù)優(yōu)惠券表中冗余了部分券規(guī)則的字段。優(yōu)惠券規(guī)則表字段較多,冗余的字段不能很多,要在性能和字段數(shù)之間做好平衡。
四、總結(jié)及展望
最后對(duì)優(yōu)惠券系統(tǒng)進(jìn)行一個(gè)總結(jié):
- 不停機(jī)遷移,平穩(wěn)過(guò)渡。自獨(dú)立后已穩(wěn)定運(yùn)行2年,性能足以支撐vivo商城未來(lái)3-5年的高速發(fā)展。
- 系統(tǒng)解耦,迭代效率大幅提升。
- 針對(duì)業(yè)務(wù)問(wèn)題,原則是選擇合適實(shí)用的方案。
- 具備完善的優(yōu)惠券業(yè)務(wù)能力。
展望:目前優(yōu)惠券系統(tǒng)主要服務(wù)于vivo商城,未來(lái)我們希望將優(yōu)惠券能力開(kāi)放,為內(nèi)部其他業(yè)務(wù)方提供通用一體化的優(yōu)惠券平臺(tái)。