高併發類題目的解題思路

最近也看了一些相關的題目,大概說一下這種題目的解決思路,僅作爲參考

高併發問題的本質就是:資源的有限性

流量大的網站 如何處理高併發流量問題?
首先從開發者角度看:(一、架構層面;二、網站本地項目層面)

一、架構層面

1、硬件升級
2、負載均衡
3、服務器集羣
4、分佈式結構

提示一下:
負載均衡:
是一種優化手段,目的是爲了讓集羣中的每臺機器的負載保持均衡,這樣就不會出現集羣中某臺機器掛了的情況;

集羣:
多臺機器做相同的業務,對外如一臺機器在做事情一樣,集羣中任意一臺機器掛了沒有影響,因爲其他機器還在工作;

分佈式:
一個業務在不同的物理點上做,比如web服務器、應用服務器、數據庫服務器,這三個節點分開部署在不同的機器上,共同完成一個業務;分佈式的特點是,每個節點都不能掛,否則這個業務就不能完成了;當然,我們可以給分佈式中的每個節點都做集羣處理,這樣可以降低分佈式系統的單節點故障;

所以,針對自己業務量大小,對上述的負載均衡、服務器集羣、分佈式結構,任意選用方案。

二、網站本地項目層面
1、頁面靜態化
2、緩存技術(Memcache、Redis等)
3、數據庫優化
4、CDN
5、禁止盜鏈
6、控制大文件的上傳下載

以上參考:https://blog.gaomeluo.com/archives/chulibingfa/

另外,從用戶視角來看(客戶端和服務端)

高併發帶來的問題
服務端的處理和響應會越來越慢,甚至會丟棄部分請求不予處理,更嚴重的會導致服務端崩潰。

高併發處理的基本思路
1)從客戶端看
儘量減少請求數量,比如:依靠客戶端自身的緩存或處理能力

儘量減少對服務端資源的不必要耗費,比如:重複使用某些資源,如連接池客戶端處理的基本原則就是:能不訪問服務端就不要訪問

2)從服務端看
增加資源供給,比如:更大的網絡帶寬,使用更高配置的服務器,使用高性能的Web服務器,使用高性能的數據庫

請求分流,比如:使用集羣,分佈式的系統架構

應用優化,比如:使用更高效的編程語言,優化處理業務邏輯的算法,優化訪問數據庫的SQL

基本原則:分而治之,並提高單個請求的處理速度

高併發處理的基本手段

1)客戶端發出請求層面,常見的手段有:
儘量利用瀏覽器的緩存功能,減少訪問服務端,比如:js、css、圖片等
可以考慮使用壓縮傳輸的功能,減少網絡流量,也會提高傳輸速度
考慮使用異步請求,分批獲取數據

2)前端接收客戶端請求層面,常見的手段有:
動靜分離,部分靜態資源可以直接從Nginx返回
按請求的不同,分發到不同的後端進行處理,比如:負載均衡、業務拆分訪問等
前面再加上一層來做多個Nginx的負載均衡,比如:LVS、F5等
還可以在更前面使用CDN服務
還可以對動態內容進行緩存,儘量減少訪問後端服務

3)Web服務器層面,常見的手段有:
使用最新的JVM,並進行配置優化
對Web服務器進行配置優化,比如:調整內存數量、線程數量等
提供多個能提供相同服務的Web服務器,以實現負載均衡
仔細規劃Web服務器上部署的應用規模
對Web服務器進行集羣

4)Web應用層面,常見的手段有:
動態內容靜態化
Java開發優化
優化處理業務邏輯的算法
合理高效的利用緩存
優化訪問數據庫的Sql,可以考慮利用存儲過程等數據庫的能力
合理使用多線程,加快業務處理
部分業務可以考慮內存數據庫,或者是進行純內存處理
儘量避免遠程調用、大量I/O等耗時的操作
合理規劃事務等較爲耗資源的操作
合理使用異步處理
對部分業務考慮採用預處理或者預計算的方式,減少實時計算量
內部系統間的業務儘量直接調用、直接處理,減少WebService、工作流等

5)數據庫層面,常見的手段有:
合理選擇數據庫的引擎,比如Mysql的InnoDB與MyISAM引擎
進行配置優化
可以考慮使用存儲過程來處理複雜的數據邏輯
數據庫集羣,進行讀寫分離
合理設計數據庫的表結構、索引等
分庫、分表,降低單庫、單表的數據量

 

以上參考:https://juejin.im/entry/5b58284ce51d451949093d09

 

另外,還有一些大流量和高併發的常規應對手段
擴容、動靜分離、緩存、服務降級和限流。

(以下整體會有點亂,可以大概熟悉一下)

限流的常用算法和實踐思路
目前主流的算法主要有三種:令牌桶算法、漏桶算法和計數器算法。

令牌桶算法:主要限制流量的流入速率,允許出現一定程度的突發流量。Nginx的限流模塊就是使用的這種算法實現的。

每秒會有r個令牌按照固定速率放入桶中。
桶的容量是固定不變的,如果桶滿了再放入令牌,則溢出。
若桶中的可用令牌不足,則改請求會被進行限流處理(被拋棄或緩存)。

漏桶算法:主要限制流量的流出速率,並且流出速率是固定不變的
可以以任意速率向桶中流入水滴。
桶的容量是固定不變的,如果桶滿了則溢出。
按照固定的速率從桶中流出水滴。
Google的Guava也實現了基於令牌桶算法那樣的平均速率限流,RateLimiter抽象類。

Nginx可以使用限流模塊在接入層實現令桶牌算法限流,
limit_zone 定義每個IP的session空間大小。
limit_zeq_zone定義每個IP每秒允許發起的請求數。
limit_conn 定義每個IP能夠發起的併發連接數。
limit_req 等待處理的請求隊列數量。
生產環境中的商品搶購可以使用計數器算法,具體不同的sku限流規則配置在配置中心內,支持動態更改。可搶購次數的扣減操作,既可以用redis,也可以用JVM。如果是集羣並且選擇用JVM,則要根據總併發數量除以集羣數量,得出單臺機器的併發數。(比如總併發數5000,集羣機器10臺,則每臺機器的併發爲5000/10=500)。

搶購商品高併發讀需求
對於一件搶購商品的流量來說,因爲key是同一個,所以流量必然會都引入到同一個redis緩存節點中,這時就容易出現單點故障。因此有下面兩種解決方式:
1. 在每個master節點都掛slave從節點,當主節點掛了可以自動頂上。
2. 多級Cache方案,多用LocalCache來過濾掉一部分流量。
- 本地緩存一般只緩存一些熱點商品數據,緩存內容一般是商品詳情和商品庫存。
- 本地緩存跟分佈式緩存的同步一般有兩種方式:一種是定時主動拉取更新策略。這種會存在一定時間的不一致,要視業務情況而定,例如庫存,暫時的不一致導致超賣,單到真正下單的時候還會再進行庫存的判斷,所以影響較小,可以接受。這種方式要注意關掉緩存的定時失效,防止當用戶流量突然過大,都到分佈式緩存中拉取數據;第二種方式是每次商品更新,都發佈一個消息,訂閱此消息的節點監聽到後再更新本地緩存的內容。

實時熱點自動發現方案
可以將交易系統產生的相關數據,以及在上游系統中埋點上報的相關數據異步寫入日誌系統中,然後通過實時熱點自動發現平臺對收集到的日誌數據做調用次數統計和熱點分析。數據符合熱點條件後,就立即通知交易系統做好熱點保護。

redis使用watch命令實現高併發搶購需求
一般高併發這裏,不用悲觀鎖,會迅速增加系統資源;而使用隊列,容易造成請求堆積,內存效果過快。所以一般使用樂觀鎖,可以用redis的watch命令實現。
watch命令會監視給定的key,當exec時,如果監視的key從調用watch後發生過變化,則事務會失敗。注意watch的可以是對整個連接有效的,事務也一樣。如果連接斷開,監視和事務都會被自動清除。當然exec,discard,unwatch命令都會清除連接中的所有監視。


緩存雪崩,緩存穿透,緩存併發,緩存預熱,緩存算法
緩存雪崩:可能是因爲數據未加載到緩存中,或者緩存同一時間大面積的失效,從而導致所有請求都去查數據庫,導致數據庫CPU和內存負載過高,甚至宕機。解決思路:
加鎖計數(即限制併發的數量,可以用semphore)或者起一定數量的隊列來避免緩存失效時大量請求併發到數據庫。但這種方式會降低吞吐量。
分析用戶行爲,然後失效時間均勻分佈。或者在失效時間的基礎上再加1~5分鐘的隨機數。
如果是某臺緩存服務器宕機,則考慮做主備。
緩存穿透:指用戶查詢數據,在數據庫沒有,自然在緩存中也不會有。這樣就導致用戶查詢的時候,在緩存中找不到,每次都要去數據庫中查詢。解決思路:
如果查詢數據庫也爲空,直接設置一個默認值存放到緩存,這樣第二次到緩衝中獲取就有值了,而不會繼續訪問數據庫。設置一個過期時間或者當有值的時候將緩存中的值替換掉即可。
可以給key設置一些格式規則,然後查詢之前先過濾掉不符合規則的Key。
緩存併發:如果網站併發訪問高,一個緩存如果失效,可能出現多個進程同時查詢DB,同時設置緩存的情況,如果併發確實很大,這也可能造成DB壓力過大,還有緩存頻繁更新的問題。解決思路:
對緩存查詢加鎖,如果KEY不存在,就加鎖,然後查DB入緩存,然後解鎖;其他進程如果發現有鎖就等待,然後等解鎖後返回數據或者進入DB查詢。
緩存預熱:目的就是在系統上線前,將數據加載到緩存中。解決思路:
數據量不大的話,在系統啓動的時候直接加載。
自己寫個簡單的緩存預熱程序。

緩存算法:
FIFO算法:First in First out,先進先出。原則:一個數據最先進入緩存中,則應該最早淘汰掉。也就是說,當緩存滿的時候,應當把最先進入緩存的數據給淘汰掉。
LFU算法:Least Frequently Used,最不經常使用算法。
LRU算法:Least Recently Used,近期最少使用算法。
LRU和LFU的區別。LFU算法是根據在一段時間裏數據項被使用的次數選擇出最少使用的數據項,即根據使用次數的差異來決定。而LRU是根據使用時間的差異來決定的。
————————————————
版權聲明:本文爲CSDN博主「後海hh」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u010942020/article/details/79315067

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章