精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

秒殺系統(tǒng)架構(gòu)解析:應(yīng)對(duì)高并發(fā)的藝術(shù)

開(kāi)發(fā)
從個(gè)人角度來(lái)看,秒殺系統(tǒng)的設(shè)計(jì)套路往往適用于其他高并發(fā)場(chǎng)景,具有較高的借鑒價(jià)值。同時(shí),其特殊的挑戰(zhàn)和需求。

作者 | 蔡佳新

秒殺活動(dòng)是大家耳熟能詳?shù)馁?gòu)物方式,它伴隨著一個(gè)極端的場(chǎng)景:極度的商品供不應(yīng)求。這里面既有需求真實(shí)且迫切的用戶(hù),也有試圖從中牟利的黃牛。反應(yīng)到系統(tǒng)應(yīng)對(duì)的挑戰(zhàn)上,就是相較于以往千倍萬(wàn)倍的用戶(hù)規(guī)模,可能是真人可能是機(jī)器人,在同一瞬間對(duì)系統(tǒng)發(fā)起沖擊,需要海量的計(jì)算資源才能支撐。

對(duì)于各大電商平臺(tái)而言,爆款運(yùn)營(yíng)和促銷(xiāo)活動(dòng)的日常化已成為常態(tài),而支撐這些的秒殺系統(tǒng)自然是不可或缺的一環(huán)。同時(shí),秒殺活動(dòng)的巨大流量就像一頭洪荒之獸,若控制不當(dāng),可能會(huì)沖擊整個(gè)交易體系。因此,秒殺系統(tǒng)在交易體系中便扮演著至關(guān)重要的角色。

從個(gè)人角度來(lái)看,秒殺系統(tǒng)的設(shè)計(jì)套路往往適用于其他高并發(fā)場(chǎng)景,具有較高的借鑒價(jià)值。同時(shí),其特殊的挑戰(zhàn)和需求,需要架構(gòu)師在設(shè)計(jì)中權(quán)衡考量,這也有助于培養(yǎng)個(gè)人在權(quán)衡取舍方面的能力。

無(wú)損的技術(shù)方案

應(yīng)對(duì)高并發(fā)就好比應(yīng)對(duì)水患:

  • 通過(guò)分流讓支流分?jǐn)倝毫Γ綦x風(fēng)險(xiǎn)。對(duì)應(yīng)到軟件設(shè)計(jì)就是系統(tǒng)隔離,分割流量;
  • 通過(guò)建造水庫(kù)存儲(chǔ)洪水,再緩慢排出,削峰填谷。對(duì)應(yīng)到軟件設(shè)計(jì)就是無(wú)損消峰;
  • 通過(guò)拓寬河道,清除淤沙提高水流流速。對(duì)應(yīng)到軟件設(shè)計(jì)就是常說(shuō)的性能優(yōu)化,比如通用的多級(jí)緩存,特定場(chǎng)景的高性能庫(kù)存扣減。

因?yàn)楹罄m(xù)方案會(huì)圍繞請(qǐng)求經(jīng)過(guò)的多個(gè)層級(jí)展開(kāi),所以在介紹方案之前,我們需要先了解一個(gè)基本情況:一個(gè)請(qǐng)求打到服務(wù)器的基本鏈路為:DNS->網(wǎng)關(guān)->前端/后端,其中流量峰值也應(yīng)該逐層減少。如圖:

1.系統(tǒng)隔離

分布式系統(tǒng)由一個(gè)個(gè)發(fā)布單元共同組成。獨(dú)立的發(fā)布單元可以按需做容量伸縮,也可以在發(fā)生故障時(shí)及時(shí)做故障隔離,以保證不會(huì)出現(xiàn)個(gè)別服務(wù)故障導(dǎo)致整個(gè)系統(tǒng)不可用的情況。

秒殺活動(dòng)因?yàn)槠涓叻逯档奶匦裕砸话阄覀儠?huì)把它隔離出來(lái),成一個(gè)獨(dú)立的秒殺系統(tǒng)(常規(guī)服務(wù)都是按領(lǐng)域特性做縱切,但這里我們按品類(lèi)做橫切,帶有秒殺活動(dòng)標(biāo)的商品將會(huì)分流到獨(dú)立的秒殺系統(tǒng)集群)。

考慮到交易系統(tǒng)體量是很大的,如果為秒殺品類(lèi)把整個(gè)交易系統(tǒng)都復(fù)制一份,那成本就太大了。所以我們把隔離區(qū)分為物理隔離和邏輯隔離:

  • 把需要定制化邏輯的能力和有特殊非功能性要求的能力剝離出來(lái)做物理隔離
  • 標(biāo)準(zhǔn)化且沒(méi)有特殊非功能要求的能力就采用邏輯隔離。

畫(huà)成部署架構(gòu)如下:

首先,我們采用獨(dú)立的秒殺域名和nginx集群(物理隔離)。這樣:

  • 可以隔離流量大頭,防止峰值沖擊交易系統(tǒng)(非功能性需求);
  • 能夠靈活擴(kuò)展,針對(duì)不同時(shí)段的流量預(yù)估擴(kuò)展nginx及后邊服務(wù)的規(guī)模(非功能性需求);
  • 能夠靈活增減私有的防控邏輯,而不影響原交易系統(tǒng)(定制化邏輯)。

接著,我們將商詳頁(yè)和下單頁(yè)獨(dú)立部署(前端+BFF,物理隔離)。基于秒殺活動(dòng)的玩法特征,海量用戶(hù)在活動(dòng)快開(kāi)始時(shí)會(huì)反復(fù)刷新商詳頁(yè),在活動(dòng)開(kāi)始時(shí)又會(huì)瞬時(shí)并發(fā)到訪問(wèn)下單頁(yè),所以這兩個(gè)頁(yè)面都是承受流量沖擊的大頭,需要隔離開(kāi)(非功能性需求)。同時(shí)因?yàn)槊霘⒒顒?dòng)的特性,商品屬于極端供不應(yīng)求的場(chǎng)景,賣(mài)家占優(yōu)勢(shì),所以可以做服務(wù)降級(jí),以降低計(jì)算資源消耗、提高性能(定制化邏輯)。比如:

  • 商詳頁(yè)可以把履約時(shí)效拿掉,不再計(jì)算預(yù)計(jì)多久能到貨。還可以拿掉評(píng)價(jià)信息,不再展示評(píng)價(jià);
  • 下單頁(yè)可以不再計(jì)算優(yōu)惠金額分?jǐn)偅霘⑸唐凡粎⑴c任何疊加的優(yōu)惠活動(dòng)。僅保留必要的信息,比如商品信息,商品主圖,購(gòu)買(mǎi)按鈕,下單按鈕等等。
  • 至于結(jié)算頁(yè)、收銀臺(tái)看情況,如果流量壓力不大可以不用做物理隔離的(支付扣減庫(kù)存下單的壓力會(huì)直接傳遞到結(jié)算,但下單扣減就不需要并發(fā)支付,僅搶到的用戶(hù)需要結(jié)算,壓力就很小了。秉著降低流量影響面積的角度,這里假設(shè)下單扣減,畢竟秒殺商品也不怕客戶(hù)下單后不支付)。

最后,商品購(gòu)買(mǎi)成功還需要依賴(lài),訂單系統(tǒng)創(chuàng)建訂單,庫(kù)存系統(tǒng)扣減商品庫(kù)存,結(jié)算系統(tǒng)確認(rèn)支付等等步驟。到達(dá)這里流量相對(duì)已經(jīng)比較平穩(wěn),并且邏輯上沒(méi)有什么定制化訴求(壓力小了,沒(méi)必要圍繞性能做定制化了),所以就采用邏輯隔離復(fù)用原交易系統(tǒng)的集群。邏輯隔離有兩種實(shí)現(xiàn)思路:

  • 第一種是依賴(lài)限流框架,比如在訂單系統(tǒng)設(shè)置來(lái)源是秒殺系統(tǒng)BFF的創(chuàng)建訂單請(qǐng)求,TPS不能超過(guò)100,并發(fā)連接數(shù)不能超過(guò)20;
  • 第二種是依賴(lài)RPC框架,RPC框架可以設(shè)置分組,只要把訂單系統(tǒng)集群里面部分服務(wù)節(jié)點(diǎn)設(shè)置成“秒殺組”,再把秒殺服務(wù)BFF的客戶(hù)端也設(shè)置為“秒殺組”,那么秒殺系統(tǒng)的流量就只會(huì)打到訂單系統(tǒng)集群里面屬于“秒殺組”的節(jié)點(diǎn)上。這種隔離方式分割了集群,集群節(jié)點(diǎn)少了,出現(xiàn)故障發(fā)生過(guò)載的可能就提高了,可能會(huì)導(dǎo)致秒殺系統(tǒng)不可用。

為什么集群節(jié)點(diǎn)少了,出現(xiàn)故障發(fā)生過(guò)載的可能就提高了?就好比公里原本4條道能并行4輛車(chē),現(xiàn)在給按車(chē)輛類(lèi)型分成了機(jī)動(dòng)車(chē)和公交車(chē)專(zhuān)用,機(jī)動(dòng)車(chē)道2條。如果其中1條機(jī)動(dòng)車(chē)道發(fā)生車(chē)禍,原本分散在2條道上的車(chē)流就要匯聚在1條道,原本順暢的通行可能立馬就開(kāi)始堵車(chē)了。

2.多級(jí)緩存

多級(jí)緩存,無(wú)非就是在系統(tǒng)的多個(gè)層級(jí)進(jìn)行數(shù)據(jù)緩存,以提高響應(yīng)效率,這是高并發(fā)架構(gòu)中最常用的方案之一。

(1) DNS層

一般我們會(huì)將靜態(tài)資源掛到CDN上,借助CDN來(lái)分流和提高響應(yīng)效率。以秒殺系統(tǒng)為例,就是將秒殺前端系統(tǒng)的商詳頁(yè)和下單頁(yè)緩存到CDN網(wǎng)絡(luò)上。一個(gè)借助CDN的用戶(hù)請(qǐng)求鏈路如下:

如果用戶(hù)終端有頁(yè)面緩存就走終端本地緩存,沒(méi)有就請(qǐng)求遠(yuǎn)端CDN的域名(靜態(tài)資源走CDN域名),請(qǐng)求來(lái)到DNS調(diào)度的節(jié)點(diǎn),調(diào)度一個(gè)最近的CDN節(jié)點(diǎn),如果該CDN節(jié)點(diǎn)有頁(yè)面緩存則返回,沒(méi)有則向緣站發(fā)起溯源,請(qǐng)求就會(huì)走普通鏈路過(guò)秒殺系統(tǒng)ng到秒殺系統(tǒng)前端。

(2) 網(wǎng)關(guān)層

網(wǎng)關(guān)這個(gè)有多種組合情況,最簡(jiǎn)單的就是一個(gè)接入層網(wǎng)關(guān)加一個(gè)應(yīng)用層網(wǎng)關(guān),比如:ISV(四層)-> Nginx(七層)。以這個(gè)為例,這里的緩存優(yōu)化主要看接入層的負(fù)載均衡算法和應(yīng)用層的本地緩存和集中內(nèi)存緩存。

之所以說(shuō)緩存還要提負(fù)載均衡算法,是因?yàn)楣?jié)點(diǎn)的本地緩存的有效性和負(fù)載均衡算法是強(qiáng)綁定的。常用的負(fù)載均衡算法有輪詢(xún)(也叫取模)和一致性哈希。輪詢(xún)可以讓請(qǐng)求分發(fā)更均衡,但同個(gè)緩存key的請(qǐng)求不一定會(huì)路由到同個(gè)應(yīng)用層Nginx上,Nginx的本地緩存命中率低。一致性哈希可以讓同個(gè)緩存key路由到同個(gè)應(yīng)用層Nginx上,Nginx的本地緩存命中率高,但其請(qǐng)求分發(fā)不均衡容易出現(xiàn)單機(jī)熱點(diǎn)問(wèn)題。有一種做法是設(shè)置一個(gè)閾值,當(dāng)單節(jié)點(diǎn)請(qǐng)求超過(guò)閾值時(shí)改為輪詢(xún),可以算是自適應(yīng)性負(fù)載均衡的變種。但這種基于閾值判斷的做法在應(yīng)對(duì)真正的高并發(fā)時(shí)效果并不理想。

所以想要運(yùn)用本地緩存強(qiáng)依賴(lài)業(yè)務(wù)運(yùn)營(yíng),需要對(duì)每個(gè)熱點(diǎn)商品key有較為準(zhǔn)確的流量預(yù)估,并人為的組合這些商品key,進(jìn)而控制流量均勻的落到每個(gè)應(yīng)用層Nginx上(其實(shí)就是數(shù)據(jù)分片,然后每片數(shù)據(jù)流量一致)。這非常困難,所以筆者認(rèn)為,還是采用輪詢(xún)加集中內(nèi)存緩存比較簡(jiǎn)單有效。

一個(gè)從接入層開(kāi)始帶有本地緩存和集中內(nèi)存緩存的請(qǐng)求鏈路如下:

(3) 服務(wù)層

應(yīng)用層ngnix->秒殺系統(tǒng)BFF->訂單服務(wù),其實(shí)兩兩組合和網(wǎng)關(guān)層是一樣的場(chǎng)景。應(yīng)用層ngnix基于ngnix的負(fù)載均衡轉(zhuǎn)發(fā)請(qǐng)求到秒殺系統(tǒng)BFF,秒殺系統(tǒng)BFF基于RPC框架的負(fù)載均衡轉(zhuǎn)發(fā)請(qǐng)求到訂單服務(wù)。都面臨著負(fù)載均衡策略選擇和是否啟用本地緩存的問(wèn)題。不一樣的點(diǎn)只是緩存的粒度和啟用緩存的技術(shù)棧選擇。

(4) 多級(jí)緩存失效

多級(jí)緩存因?yàn)榫彺娣稚⒌蕉鄠€(gè)層級(jí),所以很難用單一的技術(shù)棧來(lái)應(yīng)對(duì)緩存失效的問(wèn)題,但都等到緩存過(guò)期,這種更新時(shí)延較長(zhǎng)又不一定能被業(yè)務(wù)接受。所以這里就再提下這個(gè)話題。有一個(gè)做法是基于DB的binlog監(jiān)聽(tīng),各層監(jiān)聽(tīng)自己相關(guān)的binlog信息,在發(fā)生緩存被變更的情況時(shí),及時(shí)讓集成內(nèi)存的緩存失效。本地緩存在這里還有個(gè)缺陷,就是緩存失效時(shí)需要廣播到所有節(jié)點(diǎn),讓每個(gè)節(jié)點(diǎn)都失效,對(duì)于頻繁變更的熱key就可能產(chǎn)生消息風(fēng)暴。

3.無(wú)損消峰

秒殺活動(dòng)的特點(diǎn)是瞬時(shí)高峰的流量,就像一座高聳的尖塔,短時(shí)間內(nèi)涌入大量請(qǐng)求。為這個(gè)峰值準(zhǔn)備對(duì)應(yīng)的服務(wù)集群,首先成本太高,接著單純的水平擴(kuò)展也不一定能做到(分布式架構(gòu)存在量變引起質(zhì)變的問(wèn)題,資源擴(kuò)展到一定量級(jí),原先的技術(shù)方案整個(gè)就不適用了。比如,當(dāng)集群節(jié)點(diǎn)太多,服務(wù)注冊(cè)發(fā)現(xiàn)可能會(huì)有消息風(fēng)暴;出入口的帶寬出現(xiàn)瓶頸,需要在部署上分流)。更別說(shuō)這個(gè)峰值也不受控制,想要高枕無(wú)憂(yōu)就會(huì)有很高的冗余浪費(fèi)。

所以一般我們會(huì)采用消峰的方式:

  • 一種是直接斷頭,把超出負(fù)荷的流量直接都丟棄掉,也就是我們常見(jiàn)的限流,也稱(chēng)為有損消峰(如果這是大促的訂單,砍掉的可能都是錢(qián),這個(gè)有損是真的資損);
  • 另一種就是分流,也叫消峰填谷,通過(guò)技術(shù)或者業(yè)務(wù)手段將請(qǐng)求錯(cuò)開(kāi),鋪到更長(zhǎng)的時(shí)間線上,從而降低峰值,常見(jiàn)的有MQ異步消費(fèi)和驗(yàn)證碼問(wèn)答題。

這里我們先聊下無(wú)損消峰,有損放后邊談。

(1) MQ異步消費(fèi)

MQ依賴(lài)三個(gè)特性可以做到平滑的最終一致,分別是消息堆積,勻速消費(fèi)和至少成功一次:

  • 有消息堆積才能起到蓄水池的效果,在出水口流速恒定的情況下能接住入水口瞬時(shí)的大流量;
  • 有勻速消費(fèi)才能讓下游集群的流量壓力恒定,不會(huì)被沖擊;
  • 有至少成功一次,才能保證事物最終一致。

以秒殺系統(tǒng)BFF下單操作向訂單服務(wù)創(chuàng)建訂單為例。如果沒(méi)有消息隊(duì)列(MQ),同時(shí)有100W個(gè)創(chuàng)建請(qǐng)求,訂單系統(tǒng)就必須承擔(dān)100W個(gè)并行連接的壓力。但是,如果使用了MQ,那么100W個(gè)創(chuàng)建請(qǐng)求的壓力將全部轉(zhuǎn)移到MQ服務(wù)端,訂單系統(tǒng)只需要維持64個(gè)并行連接,以穩(wěn)定地消費(fèi)MQ服務(wù)端的消息。

這樣一來(lái),訂單系統(tǒng)的集群規(guī)模就可以大大減小,而且更重要的是,系統(tǒng)的穩(wěn)定性得到了保障。由于并行連接數(shù)的減少,資源競(jìng)爭(zhēng)也會(huì)降低,整體響應(yīng)效率也會(huì)提高,就像在食堂排隊(duì)打飯一樣,有序排隊(duì)比亂搶效率更高。但是,用戶(hù)體驗(yàn)可能會(huì)受到影響,因?yàn)辄c(diǎn)擊搶購(gòu)后可能會(huì)收到排隊(duì)提示(其實(shí)就是友好提示),需要延遲幾十秒甚至幾分鐘才能收到搶購(gòu)結(jié)果。

(2) 驗(yàn)證碼問(wèn)答題

引入驗(yàn)證碼問(wèn)答題其實(shí)有兩層好處,一層是消峰,用戶(hù)0.5秒內(nèi)并發(fā)的下單事件,因?yàn)閭€(gè)人的手速差異,被平滑的分散到幾秒甚至幾十秒中;另外一層是防刷,提高機(jī)器作弊的成本。

① 驗(yàn)證碼

基本實(shí)現(xiàn)步驟如下:

  • 請(qǐng)求到來(lái)時(shí)生成1串6位隨機(jī)字符串 verification_code
  • 用特定前綴拼接用戶(hù)ID作為key,verification_code做為value存redis,超時(shí)5s
  • 生成一個(gè)圖片,將 verification_code 寫(xiě)到圖片上,返回給用戶(hù)
  • 用戶(hù)輸入圖片中字符串
  • 從redis里面取出 verification_code 做比對(duì),如果一致,執(zhí)行下單操作

但這樣其實(shí)是可以用暴力破解的,比如,用機(jī)器仿照一個(gè)用戶(hù)發(fā)起10W個(gè)請(qǐng)求攜帶不同的6位隨機(jī)字符。所以校驗(yàn)驗(yàn)證碼時(shí)可以使用 GETDEL ,讓驗(yàn)證碼校驗(yàn)無(wú)論對(duì)錯(cuò)都讓驗(yàn)證碼失效。

② 問(wèn)答題

基本實(shí)現(xiàn)思路和驗(yàn)證碼幾乎一樣。差別在于,問(wèn)答題的題庫(kù)要提前生成,請(qǐng)求到來(lái)時(shí)從題庫(kù)中拿到一組問(wèn)題和答案。然后把答案存redis,問(wèn)題塞到圖片里返回給用戶(hù)。

驗(yàn)證碼和問(wèn)答題具有很好的消峰效果。特別是問(wèn)答題,想要提高消峰效果只要提高問(wèn)題難度就行,例如,筆者曾經(jīng)在12306上連續(xù)錯(cuò)了十幾次問(wèn)答題。但是這也是用戶(hù)體驗(yàn)有損的,例如,雖然筆者當(dāng)初未能成功搶到票而感到沮喪,但這魔性的題庫(kù)依然把筆者成功逗笑。

無(wú)損消峰,無(wú)損了流量,但損失了用戶(hù)體驗(yàn)。現(xiàn)如今技術(shù)水平在不斷進(jìn)步,解決方法在增多,這些有損用戶(hù)體驗(yàn)的技術(shù)方案可能都會(huì)慢慢退出歷史舞臺(tái),就像淘寶取消618預(yù)售。

4.庫(kù)存扣減

我們知道,用戶(hù)購(gòu)買(mǎi)商品需要扣減庫(kù)存,扣減庫(kù)存需要查詢(xún)庫(kù)存是否足夠,足夠就占用庫(kù)存,不夠則返回庫(kù)存不足(這里不區(qū)分庫(kù)存可用、占用、已消耗等狀態(tài),統(tǒng)一成扣減庫(kù)存數(shù)量,簡(jiǎn)化場(chǎng)景)。

在并發(fā)場(chǎng)景,如果查詢(xún)庫(kù)存和扣減庫(kù)存不具備原子性,就有可能出現(xiàn)超賣(mài),而高并發(fā)場(chǎng)景超賣(mài)的出現(xiàn)概率會(huì)增高,超賣(mài)的數(shù)額也會(huì)增高。處理超賣(mài)問(wèn)題是件麻煩事,一方面,系統(tǒng)全鏈路刷數(shù)會(huì)很麻煩(多團(tuán)隊(duì)協(xié)作),客服外呼也會(huì)有額外成本。另一方面,也是最主要的原因,客戶(hù)搶到了訂單又被取消,會(huì)嚴(yán)重影響客戶(hù)體驗(yàn),甚至引發(fā)客訴產(chǎn)生公關(guān)危機(jī)。

(1) 實(shí)現(xiàn)邏輯

業(yè)內(nèi)常用的方案就是使用redis+lua,借助redis單線程執(zhí)行+lua腳本中的邏輯可以在一次執(zhí)行中順序完成的特性達(dá)到原子性(原子性其實(shí)不大準(zhǔn)確,叫排它性可能更準(zhǔn)確些,因?yàn)檫@里不具備回滾動(dòng)作,異常情況需要自己回滾)。

lua腳本基本實(shí)現(xiàn)大致如下:

-- 獲取庫(kù)存緩存key KYES[1] = hot_{itemCode-skuCode}_stock
local hot_item_stock = KYES[1]
-- 獲取剩余庫(kù)存數(shù)量
local stock = tonumber(redis.call('get', hot_item_stock)) 
-- 購(gòu)買(mǎi)數(shù)量
local buy_qty = tonumber(ARGV[1])
-- 如果庫(kù)存小于購(gòu)買(mǎi)數(shù)量 則返回 1, 表達(dá)庫(kù)存不足
if stock < buy_qty thenreturn1end
-- 庫(kù)存足夠 
-- 更新庫(kù)存數(shù)量 
stock = stock - buy_qty
redis.call('set', hot_item_stock, tostring(stock))
-- 扣減成功 則返回 2, 表達(dá)庫(kù)存扣減成功
return2end

但這個(gè)腳本具備一些問(wèn)題:

  • 不具備冪等性,同個(gè)訂單多次執(zhí)行會(huì)出現(xiàn)重復(fù)扣減的問(wèn)題,手動(dòng)回滾也沒(méi)辦法判斷是否會(huì)回滾過(guò),會(huì)出現(xiàn)重復(fù)增加的問(wèn)題。
  • 不具備可追溯性,庫(kù)存被誰(shuí)被哪個(gè)訂單扣減了不知道。

結(jié)合以上問(wèn)題,我們對(duì)方案做些增強(qiáng)。

增強(qiáng)后的lua腳本如下:

-- 獲取庫(kù)存扣減記錄緩存key KYES[2] = hot_{itemCode-skuCode}_deduction_history
-- 使用 Redis Cluster hash tag 保證 stock 和 history 在同個(gè)槽
local hot_deduction_history = KYES[2]
-- 請(qǐng)求冪等判斷,存在返回0, 表達(dá)已扣減過(guò)庫(kù)存
local exist = redis.call('hexists', hot_deduction_history, ARGV[2])
if exist = 1thenreturn0end

-- 獲取庫(kù)存緩存key KYES[1] = hot_{itemCode-skuCode}_stock
local hot_item_stock = KYES[1]
-- 獲取剩余庫(kù)存數(shù)量
local stock = tonumber(redis.call('get', hot_item_stock)) 
-- 購(gòu)買(mǎi)數(shù)量
local buy_qty = tonumber(ARGV[1])
-- 如果庫(kù)存小于購(gòu)買(mǎi)數(shù)量 則返回 1, 表達(dá)庫(kù)存不足
if stock < buy_qty thenreturn1end
-- 庫(kù)存足夠 
-- 1.更新庫(kù)存數(shù)量 
-- 2.插入扣減記錄 ARGV[2] = ${扣減請(qǐng)求唯一key}-${扣減類(lèi)型} 值為 buy_qty
stock = stock - buy_qty
redis.call('set', hot_item_stock, tostring(stock))
redis.call('hset', hot_deduction_history, ARGV[2], buy_qty)
-- 如果剩余庫(kù)存等于0 則返回 2, 表達(dá)庫(kù)存已為0
if stock = 0thenreturn2end
-- 剩余庫(kù)存不為0 返回 3 表達(dá)還有剩余庫(kù)存
return3end
  • 利用Redis Cluster hash tag保證stock和history在同個(gè)槽,這樣lua腳本才能正常執(zhí)行。
  • 利用hot_deduction_history,判斷扣減請(qǐng)求是否執(zhí)行過(guò),以實(shí)現(xiàn)冪等性。
  • 借助hot_deduction_history的value值判斷追溯扣減來(lái)源,比如:用戶(hù)A的交易訂單A的扣減請(qǐng)求,或者用戶(hù)B的借出單B的扣減請(qǐng)求。
  • 回滾邏輯會(huì)先判斷hot_deduction_history里面有沒(méi)有 ${扣減請(qǐng)求唯一key} ,有則執(zhí)行回補(bǔ)邏輯,沒(méi)有則認(rèn)定回補(bǔ)成功。

但是以上邏輯依舊有漏洞,比如(消息亂序消費(fèi)),訂單扣減庫(kù)存超時(shí)成功觸發(fā)了重新扣減庫(kù)存,但同時(shí)訂單取消觸發(fā)了庫(kù)存扣減回滾,回滾邏輯先成功,超時(shí)成功的重新扣減庫(kù)存就會(huì)成為臟數(shù)據(jù)留在redis里。

處理方案有兩種,一種是追加對(duì)賬,定期校驗(yàn)hot_deduction_history中數(shù)據(jù)對(duì)應(yīng)單據(jù)的狀態(tài),對(duì)于已經(jīng)取消的單據(jù)追加一次回滾請(qǐng)求,存在時(shí)延(業(yè)務(wù)不一定接受)以及額外計(jì)算資源開(kāi)銷(xiāo)。另一種,是使用有序消息,讓扣減庫(kù)存和回滾庫(kù)存都走同一個(gè)MQ topic的有序隊(duì)列,借助MQ消息的有序性保證回滾動(dòng)作一定在扣減動(dòng)作后面執(zhí)行,但有序串行必然帶來(lái)性能下降。

(2) 高可用

存在redis終究是內(nèi)存,一旦服務(wù)中斷,數(shù)據(jù)就消失的干干凈凈。所以需要追加保護(hù)數(shù)據(jù)不丟失的方案。

運(yùn)用redis部署的高可用方案來(lái)實(shí)現(xiàn),方案如下:

  • 采用 Redis Cluster(數(shù)據(jù)分片+ 多副本 + 同步多寫(xiě) + 主從自動(dòng)選舉)。
  • 多寫(xiě)節(jié)點(diǎn)分(同城異地)多中心防止意外災(zāi)害。

定期歸檔冷數(shù)據(jù)。定期 + 庫(kù)存為0觸發(fā)redis數(shù)據(jù)往DB同步,流程如下:

CDC分發(fā)數(shù)據(jù)時(shí),秒殺商品,hot_deduction_history的數(shù)據(jù)量不高,可以一次全量同步。但如果是普通大促商品,就需要再追加一個(gè)map動(dòng)作分批處理,以保證每次執(zhí)行CDC的數(shù)據(jù)量恒定,不至于一次性數(shù)據(jù)量太大出現(xiàn)OOM。具體代碼如下:

/**
 * 對(duì)任務(wù)做分發(fā)
 * @param stockKey 目標(biāo)庫(kù)存的key值
 */
public void distribute(String stockKey){
    final String historyKey = StrUtil.format("hot_{}_deduction_history", stockKey);
    // 獲取指定庫(kù)存key 所有扣減記錄的key(一般會(huì)采用分頁(yè)獲取,防止數(shù)據(jù)量太多,內(nèi)存波動(dòng),這里偷懶下)
    final List<String> keys  = RedisUtil.hkeys(historyKey, stockKey);
    // 以100為大小,分片所有記錄 key
    final List<List<String>> splitKeys = CollUtil.split(keys, 100);
    // 將集合分發(fā)給各個(gè)節(jié)點(diǎn)執(zhí)行
    map(historyKey, splitKeys);
}
/**
 * 對(duì)單頁(yè)任務(wù)做執(zhí)行
 * @param historyKey 目標(biāo)庫(kù)存的key值
 * @param stockKeys  要執(zhí)行的頁(yè)面大小
 */
public void mapExec(String historyKey, List<String> stockKeys){
    // 獲取指定庫(kù)存key 指定扣減記錄的map
    final Map<String, String> keys = RedisUtil.HmgetToMap(historyKey, stockKeys);
    keys.entrySet()
        .stream()
        .map(stockRecordFactory::of)
        .forEach(stockRecord ->{
            //(冪等+去重)扣減+保存記錄
            stockConsumer.exec(stockRecord);
            //刪除redis中的 key 釋放空間
            RedisUtil.hdel(historyKey, stockRecord.getRecordRedisKey());
        });
}

(3) 為什么不走DB

商品庫(kù)存數(shù)據(jù)在DB最終會(huì)落到單庫(kù)單表的一行數(shù)據(jù)上。無(wú)法通過(guò)分庫(kù)分表提高請(qǐng)求的并行度。而在單節(jié)點(diǎn)的場(chǎng)景,數(shù)據(jù)庫(kù)的吞吐遠(yuǎn)不如redis。最基礎(chǔ)的原因:IO效率不是一個(gè)量級(jí),DB是磁盤(pán)操作,而且還可能要多次讀盤(pán),redis是一步到位的內(nèi)存操作。

同時(shí),一般DB都是提交讀隔離級(jí)別,為了保證原子性,執(zhí)行庫(kù)存扣減,得加鎖,無(wú)論悲觀還是樂(lè)觀。這不僅性能差(搶不到鎖要等待),而且因?yàn)榉枪礁?jìng)爭(zhēng),容易出現(xiàn)線程饑餓的問(wèn)題。而redis是單線程操作,不存在共享變量競(jìng)爭(zhēng)的問(wèn)題。

有一些優(yōu)化思路,比如,合并扣減,走批降低請(qǐng)求的并行連接數(shù)。但伴隨而來(lái)的是集單的時(shí)延,以及按庫(kù)分批的訴求;還有拆庫(kù)存行,商品A100個(gè)庫(kù)存拆成2行商品A50庫(kù)存,然后扣減時(shí)分發(fā)請(qǐng)求,以此提高并行連接數(shù)(多行可落在不同庫(kù)來(lái)提高并行連接數(shù))。

但伴隨而來(lái)的是復(fù)雜的庫(kù)存行拆分管理(把什么庫(kù)存行在什么時(shí)候拆分到哪些庫(kù)),以及部分庫(kù)存行超賣(mài)的問(wèn)題(加鎖優(yōu)化就又串行了,不加總量還有庫(kù)存,個(gè)別庫(kù)存行不足是允許一定系數(shù)超賣(mài)還是返回庫(kù)存不足就是一個(gè)要決策的問(wèn)題)。

部分頭部電商還是采用弱緩存抗讀(非庫(kù)存不足,不實(shí)時(shí)更新),DB抗寫(xiě)的方案。這個(gè)的前提在于,通過(guò)一系列技術(shù)方案,流量落到庫(kù)存已經(jīng)相對(duì)低且平滑了(扛得住,不用再自己實(shí)現(xiàn)操作原子性)。

有損的技術(shù)方案

秒殺活動(dòng)有極高的瞬時(shí)流量,但僅有極少數(shù)流量可以請(qǐng)求成功。這為我們繞開(kāi)海量計(jì)算資源采用一些特定方案達(dá)到同樣的活動(dòng)效果提供了空間。因?yàn)榻^大部分流量都是要請(qǐng)求失敗的,是真實(shí)搶購(gòu)庫(kù)存失敗還是被規(guī)則過(guò)濾掉失敗,都一樣是失敗,對(duì)于參與者來(lái)說(shuō)是一樣的活動(dòng)體驗(yàn)。所以我們不用耿直地去承接所有流量,變成用一系列過(guò)濾手段,公平公正地過(guò)濾掉絕大部分流量,僅保留有限的優(yōu)質(zhì)流量可以請(qǐng)求到服務(wù)群即可。

基本思路就是,通過(guò)業(yè)務(wù)干預(yù)阻止無(wú)效流量,通過(guò)有損消峰丟棄超荷流量,通過(guò)防刷風(fēng)控?cái)r截非法流量,最終留給下游優(yōu)質(zhì)且少量的流量。如圖:

1.業(yè)務(wù)干預(yù)

(1) 提報(bào)

借助提報(bào)系統(tǒng),商戶(hù)開(kāi)展高壓力的活動(dòng)時(shí)都提早報(bào)備接受審批和調(diào)控。這樣,可以提早知道商品、價(jià)格、活動(dòng)開(kāi)始時(shí)間、面向什么地域、預(yù)計(jì)參與人數(shù)、會(huì)員要求等等信息。幫助預(yù)估出大致流量,支撐編排活動(dòng)調(diào)整活動(dòng)組合,錯(cuò)位壓力(也能不斷保持熱點(diǎn)),平滑流量,調(diào)整計(jì)算機(jī)資源應(yīng)對(duì)高并發(fā)。設(shè)置參與門(mén)檻,阻擋非目標(biāo)人群參與。

(2) 預(yù)約

借助預(yù)約系統(tǒng),對(duì)活動(dòng)做預(yù)熱、幫助預(yù)估大致參與活動(dòng)的人數(shù)幫助評(píng)估計(jì)算資源容量。引入風(fēng)控規(guī)則,提早過(guò)濾刷子人群。采用發(fā)放參與資格(類(lèi)似游戲預(yù)約測(cè)試資格和發(fā)放測(cè)試資格),控制參與人數(shù)大小。結(jié)合提報(bào)系統(tǒng)的參數(shù),過(guò)濾非目標(biāo)人群,并盡可能提高參與人員離散度(比如參與證書(shū)1W,華南華北華東華西各2500)(假設(shè)中獎(jiǎng)的人影響范圍是一個(gè)圓,人群集中這個(gè)圓就有交集,影響范圍就會(huì)減少,所以會(huì)希望離散些。但也不排除有故意集中發(fā)放創(chuàng)造熱點(diǎn)的營(yíng)銷(xiāo)手段)。

(3) 會(huì)員

借助會(huì)員系統(tǒng),篩選出優(yōu)質(zhì)用戶(hù)。愿意購(gòu)買(mǎi)會(huì)員的用戶(hù)相對(duì)粘性就比較高(可以借助會(huì)員體系做一些提高用戶(hù)粘性的舉措,比如信用分,積分,會(huì)員等級(jí),優(yōu)惠卷等等)。同時(shí)會(huì)員用戶(hù)的規(guī)模也能幫助預(yù)估活動(dòng)參與流量。

(4) 限購(gòu)

借助限購(gòu)系統(tǒng),比如加強(qiáng)特定區(qū)域市場(chǎng)覆蓋,從地區(qū)限制,僅華東可以參與購(gòu)買(mǎi);輿情公關(guān)防控,從用戶(hù)限制,自家員工禁止購(gòu)買(mǎi)(不能既做裁判也下場(chǎng)踢球);提高離散度,從商品限制,一次只能購(gòu)買(mǎi)一件,一人一個(gè)月只能購(gòu)買(mǎi)一次。

2.有損消峰

前邊講了分流的無(wú)損消峰,這里我們講直接去頭的有損消峰。常規(guī)方案就是采用限流降級(jí)手段,這也是應(yīng)對(duì)高并發(fā)必用的手段。

限流是系統(tǒng)自我保護(hù)的最底層手段。再厲害的系統(tǒng),總有其流量承載的上限,一旦流量突破這個(gè)上限,就會(huì)引起實(shí)例宕機(jī),進(jìn)而發(fā)生系統(tǒng)雪崩,帶來(lái)災(zāi)難性后果。所以達(dá)到這個(gè)流量上限后,橫豎都無(wú)法再響應(yīng)請(qǐng)求,于是直接拋棄這部分請(qǐng)求,保證有限的流量能夠正常交互便成了最優(yōu)解。

(1) 分層限流

我們知道一個(gè)請(qǐng)求會(huì)走過(guò)多個(gè)層級(jí),最終才能到達(dá)響應(yīng)請(qǐng)求的服務(wù)節(jié)點(diǎn)。假設(shè)一個(gè)請(qǐng)求會(huì)走過(guò)網(wǎng)關(guān)->單服務(wù)集群->單服務(wù)節(jié)點(diǎn)->單接口這幾個(gè)層級(jí),每個(gè)層級(jí)考慮承載上限的維度和容量都不一樣,所以一般都會(huì)有獨(dú)立的限流規(guī)則。

網(wǎng)關(guān)一般是以一個(gè)路由配置或者一組api的吞吐指標(biāo)進(jìn)行限流,具體配置大致如下:

單服務(wù)集群一般是以整個(gè)集群所有API和所有服務(wù)節(jié)點(diǎn)為吞吐指標(biāo)進(jìn)行限流(不常用),具體配置大致如下:

  • 單服務(wù)節(jié)點(diǎn)一般是以服務(wù)節(jié)點(diǎn)的負(fù)載情況來(lái)進(jìn)行限流,比如 Load(綜合計(jì)算值)、CPU、內(nèi)存等等。
  • 單接口一般是以整個(gè)集群的一個(gè)API的吞吐指標(biāo)來(lái)進(jìn)行限流。

(2) 熱點(diǎn)參數(shù)限流

除開(kāi)分層的限流,還有參數(shù)維度的限流。

比如,基于IP地址的吞吐量指標(biāo)做限流。這個(gè)維度,對(duì)公司用戶(hù)很不友好。因?yàn)橐话愎揪蛶讉€(gè)IP出口,大家都連著wifi,很容易就觸發(fā)限流。所以,一般參與秒殺活動(dòng)時(shí)還是切換回自己的4G網(wǎng),wifi再快也架不住被限流。

比如,基于熱點(diǎn)商品的吞吐量指標(biāo)做限流。在沒(méi)有商品維度限流的情況下,假設(shè)秒殺下單接口的集群并發(fā)限流為100,同一時(shí)間參與秒殺活動(dòng)的商品有10個(gè),商品A在一瞬間就搶占了80并發(fā)連接數(shù),剩下的9商品就只能分?jǐn)?0并發(fā)連接數(shù),這會(huì)嚴(yán)重影響其活動(dòng)體驗(yàn)。

限流的口徑有很多,幸運(yùn)的是它們可以組合使用。這樣就能夠確保服務(wù)在各種場(chǎng)景下都有一個(gè)可靠的底層防護(hù)。

3.防刷風(fēng)控

秒殺活動(dòng)中的供需失衡,也會(huì)吸引黑產(chǎn)用戶(hù)借助非常規(guī)手段搶購(gòu)。比如,通過(guò)物理或軟件的按鍵精靈,用比正常用戶(hù)更快的速度搶購(gòu);通過(guò)分析接口模仿下單請(qǐng)求,同時(shí)發(fā)起千萬(wàn)個(gè)請(qǐng)求,用比正常用戶(hù)更高的頻次搶購(gòu)。這些行為不僅破壞了活動(dòng)公平性,威脅到普惠和離散訴求,還對(duì)系統(tǒng)的高并發(fā)峰值帶來(lái)了新的量級(jí)的挑戰(zhàn),嚴(yán)重影響活動(dòng)的健康發(fā)展。

(1) 防刷

從更快的速度搶購(gòu)的角度很難區(qū)分是正常用戶(hù)還是黑產(chǎn)用戶(hù),但更高頻次是很好被捕捉的,畢竟正常人總不能1秒鐘千萬(wàn)次的點(diǎn)擊吧。所以我們可以針對(duì)高頻次這個(gè)場(chǎng)景構(gòu)建一些防刷手段。

(2) 基于userID限流

我們可以采用熱點(diǎn)參數(shù)限流的方式,基于用戶(hù)ID的吞吐量指標(biāo)做限流。例如,規(guī)定每個(gè)用戶(hù)ID每秒僅能發(fā)起兩次請(qǐng)求。并且,我們應(yīng)將此限流措施盡可能地置于請(qǐng)求鏈路的上游,如應(yīng)用網(wǎng)關(guān)上,以便在最外層就隔離掉主要流量,從而減少計(jì)算資源的浪費(fèi)。這樣的限流目的與常規(guī)的有損消峰略有所不同,它不僅旨在保護(hù)服務(wù)的穩(wěn)定性,也在防止黑產(chǎn)用戶(hù)的攻擊,以此維護(hù)活動(dòng)的公平性。

(3) 基于黑名單限流

依舊是采用熱點(diǎn)參數(shù)限流的方式。但不再是看吞吐量指標(biāo),而是看是否命中黑名單來(lái)實(shí)現(xiàn)限流。黑名單里面的名單,一方面靠一些內(nèi)部行為分析,比如發(fā)現(xiàn)某個(gè)用戶(hù)每秒可以請(qǐng)求千萬(wàn)次來(lái)識(shí)別(就像游戲里面發(fā)現(xiàn)外掛封號(hào))。另一方面就是靠外部風(fēng)控?cái)?shù)據(jù)的導(dǎo)入了。

(4) 風(fēng)控

風(fēng)控在系統(tǒng)防護(hù)中占據(jù)重要地位,然而其建立卻頗為艱難。健全的風(fēng)控體系需要依賴(lài)大量數(shù)據(jù),并通過(guò)實(shí)際業(yè)務(wù)場(chǎng)景的嚴(yán)苛考驗(yàn)。簡(jiǎn)單來(lái)說(shuō),風(fēng)控就像繪制用戶(hù)畫(huà)像,需要收集用戶(hù)的靜態(tài)信息,如身份證、IP、設(shè)備號(hào)(如同一設(shè)備或同一IP的多賬戶(hù)并行搶購(gòu))、信貸記錄、社保信息、工作信息等多維度信息。同時(shí),還要關(guān)注用戶(hù)的動(dòng)態(tài)信息,如是否存在每秒發(fā)起千萬(wàn)次請(qǐng)求的情況,或者用戶(hù)是否只在特定活動(dòng)中才呈現(xiàn)活躍等。

小結(jié)

高并發(fā)的主要挑戰(zhàn)在于瞬時(shí)激增的大量用戶(hù)請(qǐng)求需要同時(shí)使用大量的計(jì)算資源。為了解決這一挑戰(zhàn),互聯(lián)網(wǎng)應(yīng)用選用了水平伸縮的發(fā)展路線,即分布式架構(gòu),通過(guò)不斷橫向擴(kuò)展集群節(jié)點(diǎn)來(lái)增加計(jì)算能力。而我們列舉的方案大部分都直接或間接依賴(lài)于分布式架構(gòu)設(shè)計(jì),所以掌握分布式架構(gòu)其實(shí)就等同于掌握高并發(fā)系統(tǒng)設(shè)計(jì)的核心。

優(yōu)秀的架構(gòu)更注重權(quán)衡,而不是追求極端。應(yīng)該從業(yè)務(wù)場(chǎng)景和企業(yè)實(shí)際情況出發(fā),尋找合適且投資回報(bào)率高的方案,而非過(guò)度設(shè)計(jì)或追求最極致的解決方案。更不應(yīng)出于恐懼落后或投機(jī)取巧的心態(tài),盲目追求所謂的"最佳實(shí)踐"。

責(zé)任編輯:趙寧寧 來(lái)源: Thoughtworks洞見(jiàn)
相關(guān)推薦

2020-10-14 07:20:53

高并發(fā)

2018-09-15 04:59:01

2025-02-20 00:01:00

2021-05-14 14:52:59

高并發(fā)TPSQPS

2021-06-23 06:48:42

秒殺Java電商

2023-11-03 08:32:53

Flask高并發(fā)

2023-05-15 08:12:38

2021-08-26 08:24:33

高并發(fā)秒殺系統(tǒng)

2024-10-08 11:21:11

2025-04-08 05:00:00

2019-10-30 16:54:08

golangredis數(shù)據(jù)庫(kù)

2009-06-16 14:43:23

大型網(wǎng)站系統(tǒng)架構(gòu)

2020-04-13 08:33:39

高并發(fā)秒殺系統(tǒng)

2020-04-22 10:43:49

高并發(fā)數(shù)據(jù)阿里巴巴

2024-03-28 08:41:10

高并發(fā).NET異步編程

2022-03-18 09:11:56

高并發(fā)搶購(gòu)系統(tǒng)架構(gòu)

2019-12-03 10:46:07

PHP高并發(fā)架構(gòu)

2023-11-27 18:07:05

Go并發(fā)編程

2025-01-20 00:00:03

高并發(fā)秒殺業(yè)務(wù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

午夜在线精品偷拍| 国产精品极品| 国产女人18毛片水真多成人如厕| 国产精品白嫩美女在线观看| 欧美xxxx精品| 日本一区二区三区播放| 欧美日韩性视频| 亚洲韩国在线| 亚洲精品一区二区三区区别| 久久亚洲国产精品一区二区| 久久精品福利视频| 亚洲色偷偷色噜噜狠狠99网| 亚洲综合在线电影| 亚洲精品免费电影| 奇米精品在线| 成人h动漫精品一区二区无码 | 精品国产av无码一区二区三区| 凸凹人妻人人澡人人添| 久久精品国产精品亚洲红杏| 性欧美办公室18xxxxhd| 婷婷综合在线视频| 色先锋久久影院av| 91麻豆精品国产91久久久久| 日韩av资源在线| 中文国产字幕在线观看| 国产亚洲欧美日韩在线一区| 国产精品美女久久久久av福利| 中文字幕第2页| 国产欧美日韩综合一区在线播放| 欧美成人精品xxx| 国产黄色录像视频| 杨幂一区二区三区免费看视频| 日韩视频免费直播| 香蕉视频999| 午夜精品久久久久久久久久蜜桃| 亚洲高清在线精品| 大桥未久一区二区三区| h网站在线免费观看| 91丝袜美腿高跟国产极品老师| 51国产成人精品午夜福中文下载 | 日韩久久久久久| 17c国产在线| av亚洲一区| 日本丶国产丶欧美色综合| 奇米精品一区二区三区| 国产在线拍揄自揄拍视频| 亚洲精品一二三| 一区二区视频在线观看| av影片免费在线观看| 久久免费看少妇高潮| 久久狠狠久久综合桃花| 色婷婷在线视频| 成人高清av在线| 超碰97网站| 丰满少妇一级片| 成人深夜在线观看| 国产欧美精品一区二区三区| 蜜桃91麻豆精品一二三区| 国产成人免费网站| 成人欧美一区二区三区视频xxx| 国产视频第一页| 国产一区二区女| 成人欧美一区二区三区视频| 免费看av毛片| 91视频免费看| 日韩精品伦理第一区| av色图一区| 国产精品久久久久久久久动漫| 亚洲欧美影院| 神马午夜伦理不卡 | 潘金莲一级淫片aaaaaa播放| 久久综合九色综合欧美狠狠| 国产精品黄视频| 91精品国产乱码久久久久| 国内精品伊人久久久久av影院 | 国内精品久久久久久影视8| 国产性一乱一性一伧一色| 在线亚洲国产精品网站| 国产成人免费av| 一级特黄aaaaaa大片| 国产精品自拍一区| 国产综合动作在线观看| 好男人免费精品视频| 国产精品每日更新| www.好吊操| 欧美无毛视频| 91精品黄色片免费大全| 中文字幕精品视频在线| 欧美日韩一区二区三区视频播放| 亚洲网色网站| 亚洲激情在线观看视频免费| 色婷婷在线影院| 日韩成人精品一区| 欧美日韩第一视频| 无码视频一区二区三区| 国产一区二区毛片| 免费久久99精品国产自| 伦xxxx在线| 精品国产999| 国产成人黄色网址| 久久精品66| 最近2019年手机中文字幕| 豆国产97在线 | 亚洲| 日韩av一级电影| av在线亚洲男人的天堂| 国产爆初菊在线观看免费视频网站| 亚洲欧美日韩久久精品| 妺妺窝人体色www在线小说| 91国产精品| 亚洲日韩欧美视频| 免费中文字幕视频| 男女男精品视频| 精品久久久久久一区| 久草资源在线| 在线观看免费视频综合| 国产精品成人99一区无码| 97精品视频在线看| 日本精品久久久久影院| 韩国av免费在线| 综合电影一区二区三区| 五月婷婷深爱五月| 日韩av资源网| 欧美激情精品久久久久久蜜臀 | 亚洲精品一区二区三区香蕉| 国产精品一区二区亚洲| 老司机精品导航| 国产一级精品aaaaa看| www红色一片_亚洲成a人片在线观看_| 在线免费观看一区| 在线不卡av电影| 在线视频日韩| 精品无人区一区二区三区| 亚洲性图自拍| 日韩一区二区免费高清| 午夜精品久久久久99蜜桃最新版| 久久一本综合频道| 蜜桃麻豆www久久国产精品| 久草在线资源站资源站| 日韩视频一区二区三区在线播放| 91高清免费看| 韩国精品免费视频| 在线国产伦理一区| 欧美成人xxxx| 日韩在线观看成人| 国产精品久久久久久久久久久久久久久久| 久久精品欧美一区二区三区不卡| 欧美成人xxxxx| 西野翔中文久久精品国产| 97不卡在线视频| 香蕉视频免费看| 亚洲成av人片一区二区三区| 欧美做受高潮中文字幕| 精品二区久久| 黑人巨大精品欧美一区二区小视频| 九色91在线| 亚洲国产三级网| 日本三级小视频| 久久久亚洲精品石原莉奈| 国产精品免费成人| 国产尤物久久久| 国产免费一区二区三区在线观看| 77导航福利在线| 51午夜精品国产| 麻豆一区产品精品蜜桃的特点| 国产成人久久精品77777最新版本| wwwjizzjizzcom| 好吊妞国产欧美日韩免费观看网站| 久久噜噜噜精品国产亚洲综合| 丰满少妇被猛烈进入| 精品欧美aⅴ在线网站| 亚洲一区二区三区蜜桃| 蜜桃视频在线观看一区二区| 一区二区三区偷拍| a看欧美黄色女同性恋| 欧美亚洲国产另类| av中文字幕一区二区三区| 欧美精品黑人性xxxx| 久久97人妻无码一区二区三区| 成人网页在线观看| 成人观看免费完整观看| 日韩1区2区| 国产精品区一区| 国模套图日韩精品一区二区| 日韩中文字幕免费看| 午夜精品久久久久久久爽| 婷婷中文字幕综合| 91导航在线观看| 国v精品久久久网| 日本xxxxxxx免费视频| 亚洲一区二区日韩| 精品久久蜜桃| 国产 日韩 欧美| 88xx成人精品| 看黄网站在线| 亚洲老司机av| 99热这里是精品| 日韩欧美主播在线| 99视频只有精品| 久久久久久久久免费| 日本少妇xxx| 日本美女一区二区三区视频| 日韩黄色片在线| 日韩一区欧美| 久久综合九九| 亚洲91网站| 国产精品一区二区久久久| aaa在线播放视频| 日韩在线观看免费全| 你懂的视频在线观看| 日韩欧美成人激情| 一级黄色片网站| 日韩欧美一区视频| 一区二区三区免费高清视频| 国产精品国产三级国产aⅴ中文| 久久一区二区电影| 懂色av一区二区在线播放| 性chinese极品按摩| 亚洲一区图片| 免费拍拍拍网站| 一本一道久久a久久精品蜜桃| 日韩电影在线播放| 亚洲精品**不卡在线播he| 国产激情美女久久久久久吹潮| 四虎国产精品免费久久| 国产精品扒开腿做爽爽爽的视频| 麻豆免费版在线观看| 欧美激情中文字幕在线| 国产三级在线播放| 日韩一级黄色av| av午夜在线| 中文字幕亚洲第一| 成人影视在线播放| 国产一区二区三区中文| 美国成人毛片| 亚洲美女黄色片| 欧美zozo| 亚洲欧美在线播放| 欧洲成人av| 亚洲美女精品久久| 国产青青草在线| 在线日韩日本国产亚洲| 国产永久av在线| 正在播放亚洲1区| √新版天堂资源在线资源| 一本大道久久加勒比香蕉| 久久久资源网| 国产一区二区三区三区在线观看 | 国产精品久久久一区麻豆最新章节| 最近中文字幕在线mv视频在线| 久久夜色精品国产噜噜av | 丰满熟妇人妻中文字幕| 精品国产伦理网| 天天操天天操天天| 精品无人区乱码1区2区3区在线 | 中文字幕+乱码+中文| 欧洲精品在线观看| 亚洲专区第一页| 91精品婷婷国产综合久久性色 | 91精品美女| 国产在线拍揄自揄视频不卡99| 国产精品xnxxcom| 99在线热播| 加勒比视频一区| 欧洲精品久久| 欧美丰满日韩| 成人国产一区二区三区| 亚洲激情亚洲| 999精品网站| 精品一区二区三区在线播放| 亚洲一级片免费观看| 成人国产精品免费网站| 亚洲成人网在线播放| 最新国产の精品合集bt伙计| 久艹视频在线观看| 自拍视频一区| 国产精品一区二区三区不卡| 国产成人在线中文字幕| 久久综合久久久| 日韩精品午夜| 女仆av观看一区| 国产精品9999久久久久仙踪林| 91麻豆精品激情在线观看最新| 精品国产乱码久久久久久郑州公司 | 国产二区国产一区在线观看| 日本一区二区黄色| 丝袜诱惑制服诱惑色一区在线观看 | 国产一在线精品一区在线观看| 国产午夜福利100集发布| 天堂久久久久va久久久久| 久久精品在线视频| 成人无遮挡免费网站视频在线观看| 久精品免费视频| 美女日韩欧美| 国产精品久久久久久久久免费| 免费观看亚洲视频大全| 免费中文日韩| 成人一区二区| 国产原创中文在线观看| 久久99国产精品免费网站| 日本黄色免费观看| 中文字幕在线不卡| 999这里只有精品| 日韩视频一区在线观看| 成人不用播放器| 久久全球大尺度高清视频| 成人毛片免费| 久久青青草综合| 欧美日韩18| 男女视频在线看| 97se亚洲国产综合自在线观| 午夜剧场免费在线观看| 色综合激情久久| 色哟哟中文字幕| 精品国产一区久久久| 欧美大片免费高清观看| 国产传媒欧美日韩| 91欧美在线| 国内自拍视频一区| 99久久伊人网影院| 久久精品www人人爽人人| 欧美日韩免费一区二区三区视频| 天天干视频在线| 欧美激情三级免费| 日韩欧美三级电影| 人妖欧美1区| 国产精品视频不卡| 欧美电影在线观看免费| 在线一区高清| 可以免费看不卡的av网站| 国产69视频在线观看| 亚洲人成网站在线| 在线观看免费黄色小视频| 日韩精品在线看| 玖玖在线播放| 国内精品久久国产| 激情av一区| 色哟哟在线观看视频| 亚洲视频在线一区观看| 亚洲系列在线观看| 少妇高潮久久77777| 8av国产精品爽爽ⅴa在线观看| 麻豆精品视频| 男人的天堂成人在线| 国产男女猛烈无遮挡a片漫画| 亚洲成人av一区| 日本成人动漫在线观看| 韩国日本不卡在线| 久久婷婷国产| 国产 福利 在线| 国产中文字幕一区二区三区| 国产亚洲精品成人av久久ww| 色欲一区二区三区精品a片| 色琪琪一区二区三区亚洲区| 污视频网站免费观看| 午夜精品理论片| 久久99精品国产自在现线| 久操网在线观看| caoporm超碰国产精品| 日韩黄色在线视频| 日韩精品极品在线观看播放免费视频| 女海盗2成人h版中文字幕| 久久人人爽爽人人爽人人片av| 久久精品男女| 91制片厂在线| 精品日韩一区二区| 日韩影院在线| 日韩精品一区二区三区四区五区 | 久久69精品久久久久久久电影好| 精品视频国内| 中文字幕无码精品亚洲资源网久久| 91一区在线观看| 日韩欧美国产另类| 久久手机免费视频| 国产主播性色av福利精品一区| 国产xxxxx在线观看| 国产精品乱人伦一区二区| 99久久免费国产精精品| 亚洲一区二区三区精品在线| 黄色av小说在线观看| 欧洲亚洲女同hd| 91久久高清国语自产拍| 无码人妻一区二区三区一| 精品人伦一区二区三区蜜桃免费| av在线中文| aa日韩免费精品视频一| 免费在线亚洲| 日韩精品一区二区亚洲av性色| 欧美不卡一区二区三区四区| 精品国产免费人成网站| 免费国产成人看片在线| 久久这里只有精品6| 国产剧情久久久| 欧美一级视频一区二区| 91蜜臀精品国产自偷在线| 久久精品女同亚洲女同13| 欧美日韩二区三区| 日韩电影毛片| 伊人久久在线观看| 中文在线资源观看网站视频免费不卡 | 国产又黄又粗又猛又爽的视频|