国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

一種高性能搶紅包系統(tǒng)的設(shè)計與實現(xiàn)

2022-10-15 13:17劉磊陳華溢姚文輝
現(xiàn)代信息科技 2022年14期
關(guān)鍵詞:總金額隊列個數(shù)

劉磊,陳華溢,姚文輝

(廣東開放大學(xué)(廣東理工職業(yè)學(xué)院),廣東 廣州 510091)

0 引 言

據(jù)統(tǒng)計,2018年春節(jié)微信參與搶紅包的峰值達到8.1 億次/分鐘,2019年春節(jié)支付寶搶紅包的峰值達到每秒4.4 萬筆,2022年春節(jié)搶紅包大戰(zhàn)總額超80 億,搶紅包已蔚然成為一種中國人特有的社交潮流,在全民狂歡的背后,強大、高效的搶紅包系統(tǒng)作為基礎(chǔ)架構(gòu)支撐起了海量紅包數(shù)據(jù)處理,筆者從搶紅包系統(tǒng)的業(yè)務(wù)分析出發(fā),嘗試設(shè)計和實現(xiàn)一種基于B/S 架構(gòu)的通用搶紅包系統(tǒng),能同時適用于手機端、桌面端、平板端,而不僅局限于APP 內(nèi)部。

搶紅包系統(tǒng)涉及發(fā)紅包用戶和搶紅包用戶,一個典型的搶紅包業(yè)務(wù)為:一個發(fā)紅包用戶填寫紅包個數(shù)、總金額等信息發(fā)出紅包,紅包數(shù)據(jù)存入數(shù)據(jù)庫,系統(tǒng)并將消息推送給搶紅包的用戶;多個搶紅包用戶收到紅包消息,點擊開始搶紅包,發(fā)送搶的請求到服務(wù)端,服務(wù)端根據(jù)紅包分配算法,從總金額生成一個小金額給搶到紅包的用戶,總金額值減小,紅包個數(shù)減一,當(dāng)大紅包被用戶搶完,紅包個數(shù)和總金額減到零,搶到的紅包明細數(shù)據(jù)存入數(shù)據(jù)庫,這樣就完成了一個搶紅包過程,示意圖如圖1所示。搶紅包業(yè)務(wù)通常規(guī)定,紅包有效期為24 小時,同一用戶對同一紅包只能搶一次。通過分析可知,一個紅包發(fā)出往往會被瞬間搶完,超過24 小時紅包即為失效,系統(tǒng)具有“短時間”特點;一次搶紅包活動搶到的人等于紅包個數(shù),這個數(shù)字在發(fā)紅包時可以確定,不會太大,但參與搶的人通常大于紅包個數(shù),假設(shè)有1 億人同時發(fā)出紅包,按發(fā)和搶比例為1:9 計算,則有9 億人幾乎同時參與搶紅包,系統(tǒng)要承載海量的“高并發(fā)”請求;一個用戶發(fā)出紅包,多個用戶搶紅包,實質(zhì)是有限資源的瞬時競爭,是將一個大金額數(shù)字生成多個小金額數(shù)字,數(shù)據(jù)的存取和金額計算都需要耗時,用戶發(fā)出搶紅包請求是搶成功了、還是搶完了、或者是已搶過,都要最快響應(yīng),系統(tǒng)有“高性能”的需求。綜上所述,設(shè)計一個魯棒的搶紅包系統(tǒng)在功能上要具備搶和發(fā)的能力,在性能上要達到高性能、高并發(fā)的要求。

圖1 搶紅包示意圖

1 系統(tǒng)設(shè)計

1.1 功能設(shè)計

為著重驗證搶紅包功能,筆者設(shè)計了一個業(yè)務(wù)具有典型性的搶紅包系統(tǒng),功能設(shè)計為:

(1)用戶注冊登錄:發(fā)紅包用戶和搶紅包用戶都要注冊賬號,使用賬號登錄系統(tǒng)。

(2)發(fā)紅包:用戶填寫紅包個數(shù)、總金額等信息發(fā)出紅包。

(3)紅包列表:用戶登錄成功后,可以查看所有能夠參與的搶紅包列表,以標(biāo)記區(qū)別顯示正在搶、已搶過、已搶完、已失效四種狀態(tài)。

(4)搶紅包:用戶查看列表,點擊搶紅包,后端執(zhí)行紅包分配過程,返回前端搶到的結(jié)果。

(5)手氣最佳:顯示單個紅包被搶到的最大金額。

(6)紅包排行榜:降序顯示單個紅包被搶到的數(shù)據(jù)明細。

(7)我收到的紅包:以列表形式展示用戶搶到的紅包數(shù)據(jù)。

(8)我發(fā)出的紅包:以列表形式展示用戶發(fā)出的紅包數(shù)據(jù)。

1.2 數(shù)據(jù)庫設(shè)計

圍繞紅包業(yè)務(wù)和功能分析,本方案數(shù)據(jù)庫設(shè)計三個核心實體對象:用戶、紅包、清單。用戶實體記錄注冊登錄信息,用戶ID 設(shè)置為主鍵;紅包實體記錄一個紅包的發(fā)包者、紅包個數(shù)、總金額、附言、創(chuàng)建時間等信息,紅包ID 設(shè)置為主鍵;清單記錄用戶搶紅包的明細,即哪個用戶搶了哪個紅包,搶到的金額是多少,字段包括搶包者ID、紅包ID、搶到的金額、搶到的時間等。根據(jù)業(yè)務(wù)分析,一個用戶可以發(fā)多個紅包,一個紅包只能被一個用戶發(fā)出,用戶與紅包是一對多的關(guān)系,同時業(yè)務(wù)要求同一用戶對同一紅包不能重復(fù)搶,也就是清單表不能插入用戶ID和紅包ID兩者都相同的記錄,解決策略是只需要將紅包ID 與用戶ID 組成清單表的聯(lián)合主鍵即可。本紅包系統(tǒng)數(shù)據(jù)庫模型設(shè)計如圖2所示。

圖2 數(shù)據(jù)庫模型圖

1.3 流程設(shè)計

用戶發(fā)紅包的流程是:用戶在前端錄入數(shù)據(jù),點擊發(fā)出紅包,系統(tǒng)后端推送通知消息給搶紅包的用戶。用戶搶紅包的流程是:用戶在前端收到紅包提示信息,查看紅包列表,點擊搶紅包,發(fā)送請求到后端服務(wù)器,服務(wù)器通過計算判斷返回前端響應(yīng)信息,若剩余金額和剩余紅包個數(shù)為0,返回“已搶完”;若搶到的用戶隊列包含該用戶ID,則返回“已搶過”;若剩余金額和剩余紅包個數(shù)不為0,且不包含該用戶ID,則從剩余金額分配出一個小金額給該用戶,返回“搶紅包成功”,顯示搶到的金額。系統(tǒng)交互流程設(shè)計如圖3所示。

圖3 系統(tǒng)交互流程圖

1.3.1 紅包分配算法

大量用戶搶有限的紅包金額,實質(zhì)是把一個大數(shù)根據(jù)一定算法分解成個小數(shù)的過程,小數(shù)的范圍是[min,max]??紤]搶紅包的高并發(fā)性,在兼顧公平的同時,紅包分配算法越簡單則越高效,運行越快則“資源競爭排隊時間”越短,系統(tǒng)性能和并發(fā)處理能力則越高。從不同角度設(shè)計有不同紅包算法,本方案設(shè)計了一種快速生成隨機紅包的算法。

算法原理:

(1)規(guī)定,因人民幣最小金額為1 分,生成紅包的金額最小為0.01 元。

(2)若紅包個數(shù)是一個,則生成紅包金額直接使用總金額。

(3)若紅包個數(shù)是多個,則取0.01 與2 倍紅包均值之間的隨機數(shù),紅包均值=剩余總金額/剩余個數(shù),即每輪生成的隨機紅包金額最小為0.01,最大為2 倍紅包均值,使用2 倍紅包均值做最大值可以保證每輪生成的紅包金額不會相差太大。

(4)每生成一次紅包,總金額減去生成的金額,紅包個數(shù)減一,直至紅包個數(shù)值為一,也就是最后一個紅包,金額使用剩余的金額,不再隨機生成。

假設(shè)剩余紅包總金額為,剩余紅包個數(shù)為,每輪生成的紅包金額為,算法公式為:

使用Java 實現(xiàn)以上算法,關(guān)鍵代碼為:

以10 人搶100 元大紅包為例,一開始紅包的數(shù)量為10、金額為100,同一個用戶對同一個紅包只能搶一次,也就是要經(jīng)過10 輪才能搶完,10 位不同用戶搶到的金額經(jīng)過算法隨機計算得到,經(jīng)測試,其中一種分配情況如表1所示,本案例在筆者機器上經(jīng)100 000 次運行,計算平均耗時約為7 微秒,可見使用本算法在內(nèi)存生成紅包的速度是很快的。

表1 以10 人搶100 元紅包為例

1.3.2 發(fā)紅包結(jié)構(gòu)設(shè)計

發(fā)紅包用戶(簡稱發(fā)包者)的動作是封一個紅包拋出去,封裝的紅包關(guān)鍵數(shù)據(jù)包括發(fā)包者ID、紅包ID、個數(shù)、總金額等,為應(yīng)對同時發(fā)紅包的請求超過系統(tǒng)的并發(fā)處理能力,可在流量高峰階段使用隊列技術(shù)減緩對服務(wù)器的沖擊。發(fā)紅包的實現(xiàn)結(jié)構(gòu)設(shè)計為:

(1)發(fā)包者在前端填寫紅包數(shù)據(jù)并向服務(wù)器提交。

(2)若同時發(fā)包提交請求超過一定量級,可先將請求放入發(fā)包隊列。

(3)服務(wù)器先將紅包數(shù)據(jù)存入緩存,緩存模塊基于內(nèi)存運行,因為內(nèi)存的存取性能遠遠大于硬盤,將搶紅包的過程放在內(nèi)存完成性能是很高的,為保證緩存模塊中單個紅包數(shù)據(jù)的全局唯一性,這時可以通過Random 提前生成全局唯一ID 作為紅包主鍵。

(4)紅包數(shù)據(jù)在緩存之后,進入入庫隊列,被推送到數(shù)據(jù)庫進行持久化存儲。

(5)同時,紅包數(shù)據(jù)進入紅包廣播隊列,被推送到眾多搶包者客戶端,搶包者拿到紅包ID 準(zhǔn)備發(fā)起搶紅包流程。發(fā)紅包實現(xiàn)結(jié)構(gòu)設(shè)計如圖4所示。

圖4 發(fā)紅包實現(xiàn)結(jié)構(gòu)

1.3.3 搶紅包結(jié)構(gòu)設(shè)計

大量用戶爭搶一個紅包,實質(zhì)是有限資源在高并發(fā)情況下的搶占,這就存在高并發(fā)競爭的問題,紅包在發(fā)出時是有個數(shù)限制的,也就是說在發(fā)出時就能估算有效搶到紅包用戶的個數(shù),超過紅包個數(shù)的用戶訪問請求,紅包已經(jīng)分配完,再去爭搶是無意義的,所以當(dāng)搶紅包的請求并發(fā)量比較大時,可以設(shè)置一層請求過濾隊列,通過計數(shù)器統(tǒng)計,在紅包個數(shù)內(nèi)的請求直接放入,一旦紅包已經(jīng)搶完,紅包個數(shù)減為零,后面的請求不再放入,直接返回“紅包已搶完”,搶紅包的過程在內(nèi)存完成,紅包數(shù)據(jù)和搶到的用戶列表都暫存在緩存,這樣可保證最快的響應(yīng)性能,等紅包搶完,則將搶到紅包的用戶ID 和金額批量入庫。搶紅包的實現(xiàn)結(jié)構(gòu)設(shè)計為:

(1)搶包者發(fā)出搶紅包的請求。

(2)當(dāng)并發(fā)量比較大時,請求先放入隊列,通過計數(shù)器統(tǒng)計,超過紅包個數(shù)直接返回。

(3)放入有效的搶紅包請求,搶紅包過程在內(nèi)存完成,根據(jù)紅包ID 從緩存拿到紅包剩余數(shù)量和剩余金額,通過紅包分配算法隨機生成一個金額給搶包者,這個計算是在內(nèi)存實時完成的,更新紅包剩余金額,紅包剩余數(shù)量減1,將更新后的紅包數(shù)據(jù)再放回緩存以備下次搶紅包使用,同時將搶到紅包的用戶ID 和金額也放入緩存,可維護一個搶到用戶的數(shù)據(jù)數(shù)組,記錄所有搶到用戶的ID 和金額。

(4)當(dāng)紅包被搶完時,將搶到紅包的用戶數(shù)據(jù)數(shù)組放入入庫隊列。

(5)入庫隊列里的數(shù)據(jù)異步批量存入數(shù)據(jù)庫。搶紅包實現(xiàn)結(jié)構(gòu)設(shè)計如圖5所示。

圖5 搶紅包實現(xiàn)結(jié)構(gòu)

2 技術(shù)實現(xiàn)

本系統(tǒng)實現(xiàn)方案采用業(yè)界流行的技術(shù)組合:Linux+Tomcat/Nginx+SSM+Bootstrap+MySQL+Redis+Mav en,這套組合被阿里、京東等互聯(lián)網(wǎng)公司廣泛應(yīng)用于大中型Web應(yīng)用,非常適于開發(fā)高并發(fā)、高性能、高擴展的Web系統(tǒng)。本方案涉及的技術(shù)點為:

(1)開發(fā)框架:后端使用SpringMVC、Spring、Mybatis 三大框架(SSM),主流的J2EE 企業(yè)級開發(fā)框架,具有輕量級、代碼侵入性低、技術(shù)成熟的特點,支持典型的三層架構(gòu):DAO(數(shù)據(jù)層)、Service(業(yè)務(wù)層)、Web(表示層)。Mybatis 是數(shù)據(jù)層框架,支持定制SQL 語句,傳參自由、靈活,結(jié)果集自動賦值,接口設(shè)計和SQL 語句分離。Spring 提供了一個統(tǒng)一托管對象的容器工廠,允許通過一致的訪問接口,訪問工廠里的任意實例。SpringMVC 是Web層框架,支持restful 風(fēng)格的URL 和MVC 開發(fā)模式。前端使用Bootstrap 框架,基于HTML5、CSS3、JQuery 技術(shù)構(gòu)建,提供了導(dǎo)航、分頁、面板等可復(fù)用的靜態(tài)組件,下拉菜單、標(biāo)簽頁、彈出框等動態(tài)插件,強大靈活的柵格布局系統(tǒng),使用Bootstrap 可以快速、高效的開發(fā)健壯和優(yōu)雅的響應(yīng)式靜態(tài)頁面。

(2)隊列技術(shù):當(dāng)并發(fā)請求達到一定量級時,超過系統(tǒng)接納能力,有可能壓垮系統(tǒng),這時可以使用隊列技術(shù)對并發(fā)請求限流,隊列能將同時發(fā)出的請求進行排隊處理,從而達到異步處理、流量削峰的目的。本方案使用請求隊列應(yīng)對同時發(fā)紅包和搶紅包的并發(fā)數(shù);為保證高性能,搶紅包的過程是在內(nèi)存完成,搶完后的紅包數(shù)據(jù)明細使用任務(wù)隊列批量異步入庫;發(fā)紅包的過程完成后,使用消息隊列及時推送通知給客戶端。

(3)緩存模塊:使用基于內(nèi)存的NoSQL 型數(shù)據(jù)庫Redis,Redis 性能非常高,經(jīng)測試每秒鐘SET 操作可執(zhí)行110 000 次、GET 操作可執(zhí)行81 000 次,Redis 支持原子性操作,也可將一組命令封裝以事務(wù)的方式執(zhí)行,即事務(wù)包括內(nèi)的命令要么都執(zhí)行,要么都不執(zhí)行,保證數(shù)據(jù)一致性。本方案使用Redis 緩存紅包數(shù)據(jù),Redis 支持以鍵值(Key-Value)存儲數(shù)據(jù),每個紅包維護兩組數(shù)據(jù),大紅包數(shù)據(jù)使用紅包ID 標(biāo)識,記錄剩余個數(shù)和剩余金額,小紅包數(shù)據(jù)使用同樣的紅包ID 標(biāo)識(為避免重復(fù),可取反),記錄搶包者ID 和搶到的金額,大紅包經(jīng)過算法分配生成小紅包明細,過程都在內(nèi)存完成,保證了高性能,存儲結(jié)構(gòu)如圖6所示。

圖6 緩存的紅包數(shù)據(jù)

(4)原子計數(shù):一個紅包發(fā)出時,小紅包的數(shù)量決定了有多少人能搶到紅包,也就是有效搶紅包的請求是可以確定的,對同一個紅包,可能有非常多的搶包者同時發(fā)送搶紅包請求,在能夠確定紅包數(shù)量的基礎(chǔ)上,對放入的請求進行原子計數(shù),當(dāng)數(shù)目和紅包個數(shù)相等時,即紅包被搶完,后面的請求無須再放入,直接返回“已搶完”,既能提高響應(yīng)速度又能減輕系統(tǒng)壓力。本方案使用Redis 兩個原子性的操作命令incr、decr 完成計數(shù),以紅包ID 為key,每次放入一個搶紅包請求,計數(shù)就加1,在Redis 中使用代碼:redis>incr key,在Spring 環(huán)境中使用代碼:Long incrementId= redisTemplate.opsForValue().increment(key,1)。

2.1 集群化部署架構(gòu)

理論上,一臺服務(wù)器若能頂住1 000 的并發(fā)量,兩臺服務(wù)器就能頂住2 000 的并發(fā)量,一般來說,當(dāng)上線的Web 系統(tǒng)并發(fā)量達到一定數(shù)量級時,都可以通過大規(guī)模服務(wù)器集群化部署提高系統(tǒng)的抗壓能力,也就是常說的“當(dāng)一頭牛拉不動時,那就用三頭?!?。本方案設(shè)計的系統(tǒng)架構(gòu)、選用的開發(fā)框架都非常適于以集群的方式運行,對于實際線上的搶紅包系統(tǒng),通過不斷增加服務(wù)器可以快速提高系統(tǒng)的并發(fā)處理能力。本系統(tǒng)線上集群化部署可以分為五層:

(1)CDN 緩存層:緩存靜態(tài)化資源。

(2)負載均衡層:根據(jù)訪問量,負責(zé)將請求智能轉(zhuǎn)發(fā)到不同服務(wù)器。

(3)Web 應(yīng)用層:在Tomcat 集群上部署相同的Web應(yīng)用。

(4)Redis 緩存層:在內(nèi)存緩存搶紅包過程產(chǎn)生的數(shù)據(jù)。

(5)數(shù)據(jù)存儲層:數(shù)據(jù)落地,使用主從庫同步、讀寫庫分離、分庫分表等技術(shù)增強抗壓能力。線上搶紅包系統(tǒng)集群化部署方案參考如圖7所示。

圖7 搶紅包系統(tǒng)集群化部署方案

2.2 系統(tǒng)測試

為了測試本文設(shè)計的搶紅包系統(tǒng)的性能,筆者在PC機上進行了兩組模擬實驗,硬件配置為:CPU Core i5 3.3 GHz、內(nèi)存8 GB;軟件配置為:Tomcat 7.0、JDK 1.7、Redis 3.0、MySQL 5.5。

2.2.1 測試紅包分配算法

為了測試本文設(shè)計的紅包分配算法的公平性,筆者模擬10 人搶100 元紅包,每輪產(chǎn)生10 個小紅包數(shù)據(jù),執(zhí)行1 000 000 輪,每人產(chǎn)生了1 000 000 條紅包數(shù)據(jù),將每個人的紅包數(shù)據(jù)求平均值和標(biāo)準(zhǔn)差,得到的數(shù)據(jù)為表2所示。

表2 模擬10 人搶100 元(執(zhí)行1 000 000 次)

由實驗數(shù)據(jù)可知:

(1)10 人的平均值大致相等,都在100/10 =10 附近波動,從統(tǒng)計學(xué)角度看,說明每人搶到紅包的期望值是大致相等的,也就是大家搶到的紅包面額在概率上是大致均勻分布的,都接近于理論平均值(總金額/總個數(shù))。

(2)10 人的標(biāo)準(zhǔn)差存在差異,從第1 人到第10 人逐漸增大,這表明,先生成的紅包數(shù)據(jù)波動較小,后生成的紅包數(shù)據(jù)波動較大,也就是后搶的人有較大概率拿到“手氣最佳”或者“手氣最差”,增加了搶紅包的趣味性。

2.2.2 測試搶紅包性能

使用Java 編程模擬高并發(fā)搶紅包場景,紅包個數(shù)為100 000 個,總金額為1 000 000 元,紅包數(shù)據(jù)和明細都存儲在Redis,搶紅包過程在內(nèi)存完成,同時啟動30 個線程運行搶紅包程序。通過搶完的紅包總個數(shù)除以總耗時可得到搶紅包速度,經(jīng)多次測算,每毫秒可以搶23 個,也就是每秒大致可以搶2.3 萬個紅包,可見在內(nèi)存完成搶紅包過程性能是很高的,能滿足絕大多數(shù)場景需求。另外,本方案實現(xiàn)的搶紅包系統(tǒng)作為筆者參與的電商平臺核心模塊已經(jīng)上線運行,通過生產(chǎn)環(huán)境中的性能優(yōu)化和集群化部署,在多次的促銷活動中,頂住了上萬的并發(fā)壓力,表現(xiàn)穩(wěn)定。

3 結(jié) 論

本文設(shè)計和實現(xiàn)的搶紅包解決方案,使用SSM 框架實現(xiàn)高擴展性,基于Redis 緩存實現(xiàn)高性能紅包分配算法,使用集群化部署增強系統(tǒng)并發(fā)處理能力,試驗表明本方案具有典型性,對于解決搶紅包、秒殺這類“瞬時高并發(fā)搶資源”的需求有較普遍的參考價值,本文沒有更多討論搶紅包系統(tǒng)的安全性,有待進一步研究。當(dāng)然搶紅包系統(tǒng)的線上實現(xiàn)方案不止一種,從不同角度也可以設(shè)計不同的紅包分配算法,沒有最佳和一勞永逸的方案,只有最適應(yīng)業(yè)務(wù)需求的方案,讀者可以根據(jù)場景靈活選用。

猜你喜歡
總金額隊列個數(shù)
智能網(wǎng)聯(lián)車輛隊列緊急工況控制策略設(shè)計*
隊列隊形體育教案
最強大腦
青春的頭屑
哪些電影賠了錢
想一想
認識頻數(shù)分布直方圖
2014年上半年印尼將進口蔬果60萬t
隊列操練
本社服務(wù)讀者新舉措