深入剖析優(yōu)惠券核心架構(gòu)設(shè)計
很多網(wǎng)站都有優(yōu)惠券業(yè)務(wù),但是剖析優(yōu)惠券架構(gòu)的技術(shù)文章卻很少,優(yōu)惠券看似簡單,但內(nèi)部涉及用戶、商品、平臺、店鋪等綜合維度下各種營銷玩法,復(fù)雜度一下會提高很多。所以寫了這篇文章來看看優(yōu)惠券是如何技術(shù)架構(gòu)的。
IT 界有句名言,”talk is cheap, show me the code“。廢話不都說,開始進(jìn)入正題
我們先簡單了解下優(yōu)惠券都包含哪些重要信息,做了個優(yōu)惠券信息的思維導(dǎo)圖

優(yōu)惠券創(chuàng)建完成后,接下來就是透出、使用。透出涉及的位置很多,比如活動會場、開機(jī)屏,但流量最大的還是在商品詳情頁。
而使用主要體現(xiàn)在下面幾個環(huán)節(jié):優(yōu)惠券領(lǐng)取、下單時優(yōu)惠券查詢、核銷等。另外還有一些周邊的附加操作,比如優(yōu)惠券的過期處理、數(shù)據(jù)統(tǒng)計、用戶券包展示等。接下來對于一些核心操作,我們重點剖析如何技術(shù)設(shè)計。
一、商品詳情頁展示
商品詳情、產(chǎn)品介紹是幾乎每個產(chǎn)品運(yùn)營、營銷推廣人員都會面對的工作。作為產(chǎn)品對外的傳播物料,直接影響到了產(chǎn)品的轉(zhuǎn)化,若是電商渠道更是直接影響產(chǎn)品銷售額。
商品詳情除了商品圖片、標(biāo)題、SKU規(guī)格、庫存、價格、成交記錄、評價、商品描述等信息外,還有一塊非常重要的信息,那就是優(yōu)惠券。如下圖所示,會提示商品可用的優(yōu)惠券,并引導(dǎo)用戶領(lǐng)取,并促成下單交易。

優(yōu)惠券設(shè)置除了基本信息外,還有適用的商品列表,但單獨存儲在優(yōu)惠券的關(guān)聯(lián)商品表中。ER模型如下圖所示

商品詳情頁查找優(yōu)惠券,只需要按item_id反查商品表即可,就可以查到所有配置到該商品的優(yōu)惠券。由于是通用頁面,所以無視用戶登錄屬性,所有人看到的頁面都是一樣。具體的校驗規(guī)則(比如有些券只能新人領(lǐng)取)會放在用戶”點擊領(lǐng)取“時做邏輯控制校驗。
邏輯看似簡單,但對于一個電商網(wǎng)站而言,商品詳情頁的訪問量通常是比較大的,如何支持高并發(fā)訪問,我們一般會借助緩存,有專門的”優(yōu)惠券同步中心“,將運(yùn)營發(fā)布的優(yōu)惠券按商品維度維護(hù)到Cache中,采用空間換時間的方式,提前預(yù)熱好數(shù)據(jù),這樣當(dāng)商詳頁訪問時只需要查緩存即可,可以支持比較高的QPS。
有人可能會繼續(xù)問,優(yōu)惠券有自己的生命周期,如果券過期了怎么維護(hù)緩存的數(shù)據(jù)一致性。因為商品詳情需要查優(yōu)惠券的詳細(xì)信息,所以接口內(nèi)部會引入stream流的 filter機(jī)制,會對優(yōu)惠券的可用時間做校驗計算,將失效的券過濾掉。另外,我們會發(fā)一個優(yōu)惠券過期的消息,由”優(yōu)惠券同步中心“接受MQ消息對緩存中已經(jīng)失效的優(yōu)惠券做清理。
二、優(yōu)惠券領(lǐng)取
優(yōu)惠券并不是每個人都可以領(lǐng)取的,有很多限制條件,比如”有些優(yōu)惠券只有新人可以領(lǐng)“,”有些優(yōu)惠券一天只能領(lǐng)一張“,”有些券需要完成任務(wù)或達(dá)到一定門檻才可以領(lǐng)“,等等。看似復(fù)雜,但”物以類聚人以群分“,我們可以采用相似聚合、分層來處理,一切都簡單很多。
我們簡單看下優(yōu)惠券領(lǐng)取的流程圖:

?
優(yōu)惠券的領(lǐng)取,邏輯相對簡單些,需要關(guān)注券模板、領(lǐng)取記錄,用戶標(biāo)簽等幾個維度校驗。如果滿足條件就可以給用戶發(fā)放優(yōu)惠券。
券模板校驗:
優(yōu)惠券模板本身設(shè)置領(lǐng)取時間,只有在區(qū)間時間內(nèi)才有機(jī)會領(lǐng)取優(yōu)惠券,當(dāng)然是否能最終領(lǐng)取還取決于其他條件。
券庫存。正如商品一樣,沒有庫存的商品是無法下單售賣
當(dāng)日發(fā)放限制。為了防止用戶對券哄搶,同時為了延長活動的黏性效果,會限量每天發(fā)放優(yōu)惠券數(shù)量。
優(yōu)惠券不是隨便亂發(fā)的,畢竟要計入公司的支出成本,一旦涉及到錢的問題便是個嚴(yán)肅的問題。定位好用戶群體,什么樣的優(yōu)惠券發(fā)給什么類型的用戶才能獲得最大收益。所以我們在創(chuàng)建優(yōu)惠券時,除了設(shè)置適用的商品范圍,還要限制優(yōu)惠券的用戶類型。人盡其用,物盡其才。
適用商品范圍一般在頁面展示或下單時才用到。而用戶類型則相反,需要前置控制,也就是說在用戶領(lǐng)取時校驗,一旦用戶領(lǐng)取成功就屬于用戶個人財產(chǎn),只要沒有過期都可以使用。
用戶領(lǐng)取記錄校驗:
根據(jù)券模板的領(lǐng)取條件限制,以及用戶的領(lǐng)取記錄,判斷是否還可以領(lǐng)取
用戶標(biāo)簽校驗:
有些券限制只有新人才可以領(lǐng)取。如:新人專享活動
券也可以跟用戶等級掛鉤,只有達(dá)到設(shè)置的等級才可以領(lǐng)取
黑名單用戶。用風(fēng)控掛鉤,識別風(fēng)險刷券用戶
自定義用戶。可以給用戶打一些特定標(biāo)簽。并針對該類型的用戶發(fā)放。
技術(shù)挑戰(zhàn):
風(fēng)控如何接入,領(lǐng)券接口的QPS會比較高,對風(fēng)控接口性能有較高要求
券緩存如何設(shè)計。一般會按變化的頻率做拆分。券模板本身內(nèi)容可以封裝一個緩存模型。其中的券庫存由于經(jīng)常變化,需要單獨剝離處理,采用緩存+數(shù)據(jù)庫。但如何保證兩者的數(shù)據(jù)一致性需要我們特別關(guān)注
領(lǐng)取記錄同樣采用緩存+數(shù)據(jù)庫
用戶標(biāo)簽。由于不用的優(yōu)惠券會限制發(fā)放給不用的用戶人群,所以我們會根據(jù)券模板設(shè)置的用戶標(biāo),采用策略模式,調(diào)用外部服務(wù),實時查詢用戶是否滿足領(lǐng)取條件。
另外優(yōu)惠券計算接口,也會返回不可用的優(yōu)惠券,并標(biāo)明不可用原因,引導(dǎo)用戶調(diào)整下單商品。
三、下單頁優(yōu)惠券計算
用戶對勾選的商品(也可能是購物車批量商品下單)創(chuàng)建訂單時,會計算有哪些優(yōu)惠券可以使用。

如上圖所示,頁面輸出信息很簡單,只顯示可以當(dāng)前可用且按優(yōu)惠力度排序的優(yōu)惠券,但如何計算出滿足當(dāng)前訂單的優(yōu)惠券,后臺涉及哪些復(fù)雜業(yè)務(wù)邏輯,又會遇到哪些技術(shù)難點挑戰(zhàn),下面來我們來分析下。

整體的架構(gòu)思想還是采用過濾機(jī)制,首先查出用戶下所有的優(yōu)惠券,然后根據(jù)優(yōu)惠的各種標(biāo)記位做相應(yīng)的策略處理。
渠道過濾:

上面的圖是多點APP的券包截圖,該券限制使用條件必須是”多點配送(到家可用)“,如果是”門店自提“則訂單無法使用該優(yōu)惠券。所以我們可以清楚判斷,優(yōu)惠券請求接口勢必要傳入配送方式參數(shù)。
下單時計算可用的優(yōu)惠券,首要一條就是判斷訂單中的商品是否在優(yōu)惠券的商品范圍里。常見的商品作用范圍有哪些:
單品:創(chuàng)建單品優(yōu)惠券,限制只有該商品才可以使用
部分商品:可以與活動綁定,也可以獨立設(shè)置,只有指定的這些商品才可以適用優(yōu)惠券
所有商品:全場券,所有售賣的商品都可使用。
店鋪商品:店鋪優(yōu)惠券,限制只有購買本店鋪的商品才可以使用,當(dāng)然要滿足金額門檻
商品分類:類目券,根據(jù)商品的類目屬性做適用條件
商品品牌:按品牌決定是否可以使用優(yōu)惠券
商品標(biāo)簽:為指定商品打上自定義標(biāo)簽,然后優(yōu)惠券模板中配置
指定商品/排除特殊商品:針對特殊商品做給運(yùn)營人員的靈活配置。
渠道商品:根據(jù)商品進(jìn)貨或者銷售渠道定義優(yōu)惠券范圍
區(qū)域商品:根據(jù)商品銷售區(qū)域劃分,此類優(yōu)惠券社區(qū)電商用的較多。
訂單范圍就是訂單金額滿減、滿贈、包郵等條件下可使用的優(yōu)惠券。

上圖優(yōu)惠券就是商家券,除了”商家券“的標(biāo)記外,還會設(shè)置商家的id,也就是下單的商品中屬于這家的商品才會累計校驗金額門檻。
四、優(yōu)惠券核銷

五、其他功能
優(yōu)惠券一般都有適用的商品范圍,可作為一個獨立頁面對外呈現(xiàn)。下圖是商家券的詳情頁,同時提供了”推薦“、”熱銷“、”價格“,三個維度的排序。

一般這種玩法都是借助搜索來技術(shù)實現(xiàn)的,創(chuàng)建優(yōu)惠券模板后,會以商品的維度將數(shù)據(jù)同步ES中,索引結(jié)構(gòu):
{"properties" : {"couponId" : {"type" : "long"},"itemId" : {"type" : "long"},"sort" : {"type" : "long"},"salesCount" : {"type" : "long"},"salePrice" : {"type" : "long"},"gmtCreated" : {"type" : "date","format" : "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"},"gmtModified" : {"type" : "date","format" : "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"}}}
至于搜索數(shù)據(jù)的維護(hù),尤其是商品銷量定時寫入,這些都是些常規(guī)的業(yè)務(wù)實現(xiàn),這里就不一一累述了。

用戶的卡券包實現(xiàn)很簡單,只需分頁查詢用戶的券表即可,加上過濾條件”用戶券的狀態(tài)要是未使用“。如果是社區(qū)電商,一般有區(qū)域限制,券列表展示會根據(jù)當(dāng)前區(qū)域做判斷,如果當(dāng)前區(qū)域不可用會置灰。
往期推薦
