日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

从限流削峰到性能优化,谈1号店抽奖系统架构实践

發(fā)布時(shí)間:2025/4/5 windows 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从限流削峰到性能优化,谈1号店抽奖系统架构实践 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.前言

抽獎(jiǎng)是一個(gè)典型的高并發(fā)場(chǎng)景應(yīng)用,平時(shí)流量不多,但遇到大促活動(dòng),流量就會(huì)暴增,今年的周年慶期間的日均UV就超過百萬。在過去的一年里,負(fù)責(zé)過這個(gè)項(xiàng)目的多次重構(gòu)工作,期間各種踩坑無數(shù),就以此文當(dāng)做總結(jié),來聊聊我們是如何架構(gòu)這個(gè)高并發(fā)系統(tǒng)吧。

2.整體設(shè)計(jì)詳解

在我看來,能提高服務(wù)器應(yīng)對(duì)并發(fā)的能力的方式無非兩種:

  • 限流削峰:通過降低實(shí)際抵達(dá)服務(wù)器的并發(fā)量,降低服務(wù)器處理壓力;
  • 性能優(yōu)化:從前臺(tái)到硬件,優(yōu)化系統(tǒng)各方面性能,提高服務(wù)器處理能力。
  • 接下來我們圍繞這兩個(gè)方面談?wù)勗?號(hào)店抽獎(jiǎng)系統(tǒng)中所做的工作和遇到的坑。

    整體架構(gòu)如下圖:

    2.1服務(wù)器層的限流削峰

    我們的負(fù)載服務(wù)器使用的是A10,商業(yè)的負(fù)載均衡硬件,相比nginx,雖然花不少錢,但在使用配置等方面簡單,便于維護(hù),web服務(wù)器自然是Tomcat。這里我們優(yōu)化了兩件事情。

    1.前言

    抽獎(jiǎng)是一個(gè)典型的高并發(fā)場(chǎng)景應(yīng)用,平時(shí)流量不多,但遇到大促活動(dòng),流量就會(huì)暴增,今年的周年慶期間的日均UV就超過百萬。在過去的一年里,負(fù)責(zé)過這個(gè)項(xiàng)目的多次重構(gòu)工作,期間各種踩坑無數(shù),就以此文當(dāng)做總結(jié),來聊聊我們是如何架構(gòu)這個(gè)高并發(fā)系統(tǒng)吧。

    2.整體設(shè)計(jì)詳解

    在我看來,能提高服務(wù)器應(yīng)對(duì)并發(fā)的能力的方式無非兩種:

  • 限流削峰:通過降低實(shí)際抵達(dá)服務(wù)器的并發(fā)量,降低服務(wù)器處理壓力;
  • 性能優(yōu)化:從前臺(tái)到硬件,優(yōu)化系統(tǒng)各方面性能,提高服務(wù)器處理能力。
  • 接下來我們圍繞這兩個(gè)方面談?wù)勗?號(hào)店抽獎(jiǎng)系統(tǒng)中所做的工作和遇到的坑。

    整體架構(gòu)如下圖:

    2.1服務(wù)器層的限流削峰

    我們的負(fù)載服務(wù)器使用的是A10,商業(yè)的負(fù)載均衡硬件,相比nginx,雖然花不少錢,但在使用配置等方面簡單,便于維護(hù),web服務(wù)器自然是Tomcat。這里我們優(yōu)化了兩件事情。

    a).防cc

    負(fù)載均衡作為分布式系統(tǒng)的第一層,本身并沒有好說的。唯一值得一提的是針對(duì)此類大流量場(chǎng)景,我們特意引入了防cc機(jī)制,限制用戶每分鐘的最高訪問次數(shù),超出頻率的請(qǐng)求直接拒絕,防止用戶使用腳本等方式刷請(qǐng)求。這個(gè)在我們使用的負(fù)載均衡器A10上可以自行配置,如果是nginx也有限制連接模塊可以使用,這也是流量削峰的第一層。

    b).Tomcat并發(fā)參數(shù)

    我們之前線上的Tomcat是使用默認(rèn)的參數(shù)maxThreads=500,在流量沒有上來之前沒什么感覺,但大流量情景下會(huì)拋出不少異常日志。在通過性能壓測(cè)后發(fā)現(xiàn),在并發(fā)請(qǐng)求超出400+后,響應(yīng)速度明顯變慢,后臺(tái)開始出現(xiàn)數(shù)據(jù)庫,接口等鏈接超時(shí),因此將maxThread改為了400,限制tomcat處理量,進(jìn)一步削減流量。

    2.2應(yīng)用層的限流削峰

    從這里開始,請(qǐng)求就進(jìn)入應(yīng)用代碼中了,在這一層,我們可以通過代碼來進(jìn)行流量削峰工作了,主要包括信號(hào)量,用戶行為識(shí)別等方式。

    a).信號(hào)量

    前面談到了通過Tomcat并發(fā)線程配置來攔截超出的流量,但這里有一個(gè)問題是超出的請(qǐng)求要么被阻塞,要么被直接拒絕的,不會(huì)給出響應(yīng)。在客戶端看到的是長時(shí)間沒有響應(yīng)或者請(qǐng)求失敗,然后不斷重試,我們更希望在這個(gè)時(shí)候響應(yīng)一些信息,比如說直接給出提示沒有中獎(jiǎng),通知客戶端不再請(qǐng)求,從而提高用戶體驗(yàn)。因此在這里我們使用了java并發(fā)包中的Semaphore,偽代碼如下:

    semaphore=new Semaphore(350);if (!semaphore.tryAcquire()) {return "error"; } try {execute(); } finally {semaphore.release(); }

    由于通過壓測(cè)得出的Tomcat最大線程數(shù)配置為400,這里的信號(hào)量我們?cè)O(shè)成了350,剩下50個(gè)線程用來響應(yīng)超出的請(qǐng)求。在這種情景下,我們?cè)?00個(gè)并發(fā)做過測(cè)試,由于請(qǐng)求還未抵達(dá)復(fù)雜的業(yè)務(wù)邏輯中,客戶端可以在10ms內(nèi)收到錯(cuò)誤響應(yīng),不會(huì)感到延遲或請(qǐng)求拒絕的現(xiàn)象。

    b).用戶行為識(shí)別

    Tomcat及信號(hào)量進(jìn)行的并發(fā)控制我稱之為硬削峰,并不管用戶是誰,超出設(shè)置上限直接拒絕。但我們更想做的是將非法的請(qǐng)求攔截掉,比如腳本,黃牛等等,從而保證正常用戶的訪問,因此,在公司風(fēng)控等部門同學(xué)的協(xié)助下,引入一些簡單的用戶行為識(shí)別。

  • 實(shí)時(shí)人機(jī)識(shí)別:在用戶請(qǐng)求過程中,正常用戶跟機(jī)器的請(qǐng)求數(shù)據(jù)會(huì)有差異,如果請(qǐng)求數(shù)據(jù)跟實(shí)際的數(shù)據(jù)不一致,通過實(shí)時(shí)的識(shí)別,自然就可以將這個(gè)請(qǐng)求標(biāo)識(shí)為非法請(qǐng)求,直接攔截。

  • 風(fēng)控列表:除了實(shí)時(shí)的人機(jī)識(shí)別,根據(jù)還可以根據(jù)一些賬號(hào)或者ip平時(shí)的購物等行為進(jìn)行用戶畫像識(shí)別出其中的黃牛,機(jī)器賬號(hào)等等,維持著一個(gè)列表,對(duì)于列表中的賬號(hào)可以按風(fēng)險(xiǎn)等級(jí)進(jìn)行額外的攔截。

  • 下圖一個(gè)接入用戶行為識(shí)別前后的一個(gè)流量對(duì)比圖

    可以明顯的看到,兩天的同一時(shí)刻,在未接入識(shí)別時(shí)流量峰值為60w?,接入識(shí)別后流量降為30w?。也就意味著有人通過腳本等工具貢獻(xiàn)了超過一半的請(qǐng)求量;另一個(gè)比對(duì)是,在沒有接入識(shí)別時(shí),我們一個(gè)活動(dòng)數(shù)萬獎(jiǎng)品,在活動(dòng)開始3秒鐘就已經(jīng)被抽光,而接入之后,當(dāng)活動(dòng)結(jié)束時(shí)剛好被抽完。所以,如果沒有行為識(shí)別的攔截,不少正常用戶根本抽不到獎(jiǎng)品,這點(diǎn)跟春節(jié)搶火車票是一樣的場(chǎng)景。

    c).其他規(guī)則

    其他規(guī)則包括緩存中的活動(dòng)限制規(guī)則等等,根據(jù)一些簡單的邏輯,也起到一定作用的流量削峰。

    至此,我們所有的流量削峰思路都已經(jīng)解釋完了,接下來是針對(duì)性能優(yōu)化做的一些工作。

    2.3應(yīng)用層的性能優(yōu)化

    性能優(yōu)化是一個(gè)龐大的話題,從代碼邏輯,緩存,到數(shù)據(jù)庫索引,從負(fù)載均衡到讀寫分離,能談的事情太多了。在我們的這個(gè)高并發(fā)系統(tǒng)中,性能的瓶頸在于數(shù)據(jù)庫的壓力,這里就聊下我們的一些解決思路。

    a).緩存

    緩存是降低數(shù)據(jù)庫壓力的有效手段,我們使用到的緩存分為兩塊。

  • 分布式緩存:Ycache是1號(hào)店基于MemCache二次開發(fā)的一個(gè)分布式緩存組件,我們將跟用戶相關(guān)的,數(shù)據(jù)規(guī)模大的數(shù)據(jù)緩存在Ycache中,減少不必要的讀寫操作。

  • 本地緩存:使用分布式緩存降低數(shù)據(jù)庫壓力,但仍然有一定的網(wǎng)絡(luò)開銷,對(duì)于數(shù)據(jù)量小,無需更新的一些熱數(shù)據(jù),比如活動(dòng)規(guī)則,我們可以直接在web服務(wù)器本地緩存。代表性的是EhCache了,而我們那時(shí)比較直接粗暴,直接用ConcurrentHashMap造了個(gè)輪子,也能起到同樣的效果。

  • b).無事務(wù)

    對(duì)于并發(fā)的分布式系統(tǒng)來說,數(shù)據(jù)的一致性是一個(gè)必須考慮的問題。在我們抽獎(jiǎng)系統(tǒng)中,數(shù)據(jù)更需要保證一致,活動(dòng)獎(jiǎng)品是1臺(tái)iphone,就絕不能被抽走兩臺(tái)。常見的做法便是通過事務(wù)來控制,但考慮到我們業(yè)務(wù)邏輯中的如下場(chǎng)景。

    在JDBC的事務(wù)中,事務(wù)管理器在事務(wù)周期內(nèi)會(huì)獨(dú)占一個(gè)connection,直到事務(wù)結(jié)束。

    假設(shè)我們的一個(gè)方法執(zhí)行100ms,前后各有25ms讀寫操作,中間向其他SOA服務(wù)器做了一次RPC,耗時(shí)50ms,這就意味著中間50ms時(shí)connection將處于掛起狀態(tài)。

    前面已經(jīng)談到了當(dāng)前性能的瓶頸在于數(shù)據(jù)庫,因此這種大事務(wù)等于將數(shù)據(jù)庫鏈接浪費(fèi)一半,所以我們沒有使用事務(wù),而是通過以下兩種方式保證數(shù)據(jù)的一致性。

  • 樂觀鎖:在update時(shí)使用版本號(hào)的方式保證數(shù)據(jù)唯一性,比如在用戶中獎(jiǎng)后減少已有獎(jiǎng)品數(shù)量,

    update award set award_num=award_num-1,version=version+1 where id=#{id} and version=#{version} and award_num>0
  • 唯一索引:在insert時(shí)通過唯一索引保證只插入一條數(shù)據(jù),比如建立獎(jiǎng)品id和用戶id的唯一索引,防止insert時(shí)插入多條中獎(jiǎng)記錄。

  • 2.4 數(shù)據(jù)庫及硬件

    再往下就是基礎(chǔ)層了,包括我們的數(shù)據(jù)庫和更底層的硬件,之所以單獨(dú)列一節(jié),是為了聊聊我們踩的一個(gè)坑。

    當(dāng)時(shí)為了應(yīng)對(duì)高并發(fā)的場(chǎng)景,我們花了數(shù)周重構(gòu),從前臺(tái)服務(wù)器到后臺(tái)業(yè)務(wù)邏輯用上了各種優(yōu)化手段,自認(rèn)為扛住每分鐘幾十萬流量不成問題,但這都是紙上談兵,我們需要拿數(shù)據(jù)證明,因此用JMeter做了壓測(cè)。

    首先是流量預(yù)估,我們統(tǒng)計(jì)了過往的數(shù)據(jù),預(yù)估的流量是15w/分鐘,單次請(qǐng)求性能指標(biāo)是100ms左右,因此吞吐量為150000/60~2500tps,每次請(qǐng)求100ms,即并發(fā)數(shù)為250,這只是平均的,考慮活動(dòng)往往最開始幾秒并發(fā)量最大,所以峰值并發(fā)估計(jì)為平均值的3-5倍。

    第一次我們用50個(gè)并發(fā)做壓測(cè):

    壓測(cè)結(jié)果簡直難以置信,平均耗時(shí)超600ms,峰值輕松破1000ms,這連生產(chǎn)上日常流量都扛不住,我們做了這么多手段,不應(yīng)該性能反而降低了,當(dāng)時(shí)都有點(diǎn)懷疑人生了,所以我們著手開始排查原因。

    首先查看日志發(fā)現(xiàn)數(shù)據(jù)庫鏈接存在超時(shí)

    排查發(fā)現(xiàn)配置的數(shù)據(jù)庫鏈接數(shù)為30,50個(gè)線程并發(fā)情景下會(huì)不夠,將最大鏈接數(shù)設(shè)為100.數(shù)據(jù)庫鏈接超時(shí)問題沒有了,但問題沒這么簡單,測(cè)試下來還是一樣的結(jié)果。

    然后通過VisualVM連上壓測(cè)的JVM,我們查看了線程的快照。

    (點(diǎn)擊放大圖像)

    如圖,發(fā)現(xiàn)在幾個(gè)數(shù)據(jù)庫寫方法以及一個(gè)RPC接口上的耗時(shí)占比最大。

    所以一方面我們自己著手查原因,另一方面也推動(dòng)接口提供方減少耗時(shí)。

    首先是一些常規(guī)的排查手段

  • 走讀對(duì)應(yīng)部分代碼,排查是否有鎖,或者嚴(yán)重的邏輯錯(cuò)誤如死循環(huán)等。
  • dump虛擬機(jī)內(nèi)存快照,排查是否存在死鎖。
  • 查看sql語句及其執(zhí)行計(jì)劃,確保業(yè)務(wù)邏輯合理,并走到索引。
  • ...
  • 當(dāng)時(shí)花了兩天時(shí)間毫無進(jìn)展,代碼上沒發(fā)現(xiàn)任何問題,也請(qǐng)教了很多同事,感覺已經(jīng)陷入了思維誤區(qū),然后有位同事說這不是我們程序的問題,會(huì)不會(huì)是數(shù)據(jù)庫本身或者硬件問題。我們馬上找了DBA的同事,查看測(cè)試數(shù)據(jù)庫的執(zhí)行情況,如圖:

    log file sync的Avg wait超過了60ms,查閱資料后了解到這種情況的原因可能有:

  • 連接阻塞;
  • 磁盤io瓶頸;
  • 然后我們一看,壓測(cè)環(huán)境的服務(wù)器的硬盤是一塊老的機(jī)械硬盤,而其他環(huán)境早已SSD遍地了。我們連夜把壓測(cè)環(huán)境切換到了SSD,問題解決了,最后壓測(cè)結(jié)果:單機(jī)441個(gè)并發(fā), 平均響應(yīng)時(shí)間136ms,理論上能扛住19w/分鐘的流量,比起第一次壓測(cè)有了數(shù)十倍的提升,單機(jī)即可扛住預(yù)估流量的壓力,生產(chǎn)上更不成問題了,可以上線了。

    至此,整個(gè)抽獎(jiǎng)系統(tǒng)的架構(gòu),以及我們限流削峰和調(diào)優(yōu)的所有手段已經(jīng)介紹完了,接下來展開下其他的優(yōu)化想法和感悟吧。

    3.其他優(yōu)化想法

    這里還有一些曾經(jīng)考慮過的想法供參考,可能由于時(shí)間,不適用等原因沒有做,但也是應(yīng)對(duì)高并發(fā)場(chǎng)景的思路。

  • 消息隊(duì)列:由于抽獎(jiǎng)一般會(huì)有個(gè)轉(zhuǎn)盤效果,意味著我們不需要馬上給出結(jié)果,如果引入消息隊(duì)列,無疑可以有效削峰,降低服務(wù)器壓力。如果說Tomcat的并發(fā)配置和信號(hào)量的硬削峰是把1000并發(fā)直接拒掉500來做到,而這種是把1000并發(fā)排隊(duì)每次處理500來實(shí)現(xiàn),也就是說結(jié)果上是會(huì)處理掉所有請(qǐng)求,相對(duì)來說更合理。1號(hào)店的秒殺系統(tǒng)便接入了這個(gè)功能,但由于當(dāng)時(shí)重構(gòu)時(shí)間只有兩周,評(píng)估下來時(shí)間上來不及做,因此擱置了。

  • 異步:前面談到了一個(gè)RPC接口占用了近50%的耗時(shí),經(jīng)過業(yè)務(wù)邏輯上的評(píng)估這個(gè)接口是可以異步的,所以如果有必要的時(shí)候這是一個(gè)可行的方案。

  • 讀寫分離:主備庫的同步還是有延遲的,基于一致性考慮,讀寫分離的方案被我們拋棄了,但在其他高并發(fā)場(chǎng)景,讀寫分離是一個(gè)比較常見的優(yōu)化方案。

  • 活動(dòng)拆庫:性能的瓶頸還是在數(shù)據(jù)庫,如果多個(gè)活動(dòng)并行,并且互不相干,我們完全可以按活動(dòng)拆庫,分擔(dān)數(shù)據(jù)庫壓力,不過這次的壓力還沒有達(dá)到這個(gè)量。

  • 內(nèi)存數(shù)據(jù)庫:數(shù)據(jù)庫的IO效率影響很大,把數(shù)據(jù)庫所在的機(jī)械硬盤換成SSD后有數(shù)倍性能的提升,但內(nèi)存的速度更快,相關(guān)文章已經(jīng)介紹到12306已經(jīng)全面應(yīng)用了。

  • 升級(jí)硬件:換了SSD后性能就上來了,在未來如果有了瓶頸,可以預(yù)見的是如果硬件的有了新的發(fā)展,通過升級(jí)硬件是比較省力的方式。

  • 4.幾點(diǎn)思考

  • 警惕流量,用戶量的增長:在沒有引入行為識(shí)別前,看著監(jiān)控里流量十萬十萬的上漲無疑是很高興的,但引入用戶行為識(shí)別后,我們發(fā)現(xiàn)一大半的流量可能來自于腳本。假設(shè)我們沒有做行為識(shí)別,一個(gè)普通用戶,稍微慢幾秒就得不到獎(jiǎng)品,來這么兩三次,估計(jì)就不會(huì)來參加你的活動(dòng)了,正常用戶就這么一個(gè)個(gè)流失了,這種負(fù)面影響想想就讓人背后發(fā)涼。所以當(dāng)看到用戶量快速增長,在高興的同時(shí),一定要意識(shí)到其中可能的風(fēng)險(xiǎn),引入必要風(fēng)控手段,保證真正的用戶的用戶體驗(yàn)。

  • 性能優(yōu)化是系統(tǒng)性的問題:從前臺(tái)到后臺(tái)我們考慮了很多優(yōu)化方式,但最后壓測(cè)不通過,一頭栽在了老化的硬盤上,真是一個(gè)活生生的短板理論例子,所以優(yōu)化不能單單局限代碼,JVM的層次,從頁面到硬盤,一定要通盤考慮。在遇到性能瓶頸時(shí),不要只從表面的代碼排查問題,要深入,網(wǎng)絡(luò),硬件都有可能瓶頸。

  • 關(guān)于作者

    文初開,開發(fā)工程師,15年加入1號(hào)店,現(xiàn)負(fù)責(zé)1號(hào)店購物流程的開發(fā)工作,曾負(fù)責(zé)1號(hào)店會(huì)員、抽獎(jiǎng)系統(tǒng)的開發(fā)工作,博客:https://chulung.com

    轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/8064229.html

    總結(jié)

    以上是生活随笔為你收集整理的从限流削峰到性能优化,谈1号店抽奖系统架构实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。