01 概述
????高并發(High Concurrency)是互聯網分布式系統架構設計中必須考慮的因素之一,它通常是指,通過設計保證系統能夠同時并行處理很多請求。
????高并發一方面可以提高資源利用率,加快系統響應速度,但是同時也會帶來安全性,分布式事務、死鎖等問題。
????并發:一個處理器同時處理多個任務。
????并行:多個處理器或者是多核的處理器同時處理多個不同的任務。
02?度量指標
????并發的指標一般有QPS,TPS,IOPS,并發用戶數,PV,響應時間等。
2.1?QPS
????QPS:每秒響應請求數,是一臺服務器每秒能夠相應的查詢次數,是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準, 即每秒的響應請求數,也即是最大吞吐能力。
2.2 TPS?
????Transactions Per Second,也就是事務數/秒。一個事務是指一個客戶機向服務器發送請求然后服務器做出反應的過程。客戶機在發送請求時開始計時,收到服務器響應后結束計時,以此來計算使用的時間和完成的事務個數。
????QPS基本類似于TPS,但是不同的是,對于一個頁面的一次訪問,形成一個TPS;但一次頁面請求,可能產生多次對服務器的請求,服務器對這些請求,就可計入“QPS”之中。
2.3?并發用戶數
????并發用戶數:同時承載正常使用系統功能的用戶數量。例如一個即時通訊系統,同時在線量一定程度上代表了系統的并發用戶數。
2.4?響應時間
????響應時間:系統對請求做出響應的時間。例如系統處理一個HTTP請求需要200ms,這個200ms就是系統的響應時間。一般而言,用戶感知友好的高并發系統,時延應該控制在250毫秒以內。
2.5?PV
????PV(Page View):頁面訪問量,即頁面瀏覽量或點擊量,用戶每次刷新即被計算一次。可以統計服務一天的訪問日志得到。
03?設計思路
????互聯網分布式架構設計,提高系統并發能力的方式,方法論上主要有兩種:垂直擴展(Scale Up,也叫豎向擴展)與水平擴展(Scale Out,也叫橫向擴展)。
? ??1、垂直方向:提升單機能力
????提升單機處理能力又可分為硬件和軟件兩個方面:
????硬件方向,升級服務器硬件,購買多核高頻機器,大內存,大容量磁盤等。
????軟件方向,包括用更快的數據結構(編程語言級別的并發編程),改進架構,應用多線程、協程(select/poll/epoll等IO多路復用技術),以及上性能優化各種手段,但是這種方式很容易出現瓶頸。
? ??2、水平方向:分布式集群
????為了解決分布式系統的復雜性問題,一般會用到架構分層和服務拆分,通過分層做隔離,通過微服務解耦。
????這個理論上沒有上限,只要做好層次和服務劃分,加機器擴容就能滿足需求,但實際上并非如此,一方面分布式會增加系統復雜性,另一方面集群規模上去之后,也會引入一堆服務發現、服務治理的新問題。
????因為垂直向的限制,所以,我們通常更關注水平擴展,高并發系統的實施也主要圍繞水平方向展開。
04?集群化
????單機的硬件擴展成本較高,軟件優化易出現性能瓶頸,因此利用集群解決高并發問題。負載均衡是常用的解決方案,即把前端流量分配到不同的服務節點上。
????在集群化的架構下,可以采用池化(內存池,連接池,線程池),分布式緩存,分布式消息隊列,流控技術(服務降級,應用拆分,限流)和數據庫高并發(分庫分表,讀寫分離等)提高并發能力。
????負載均衡可以分為3種:
????1、DNS負載均衡,客戶端通過URL發起網絡服務請求的時候,會去DNS服務器做域名解釋,DNS會按一定的策略(比如就近策略)把URL轉換成IP地址,同一個URL會被解釋成不同的IP地址,這便是DNS負載均衡,它是一種粗粒度的負載均衡,它只用URL前半部分,因為DNS負載均衡一般采用就近原則,所以通常能降低時延,但DNS有cache,所以也會更新不及時的問題。
????2、硬件負載均衡,通過布置F5,A10等專門的負載均衡設備到機房做負載均衡,性能高,但是價格昂貴。
????3、軟件負載均衡,利用軟件實現四層負載均衡(LVS)和七層負載均衡(Nginx)。
05?池化技術
5.1 內存池????
? ??內存池創建的方法:
????1、對于用戶申請的大塊內存使用內存映射
????2、對于小塊內存從內存池合適的鏈表中取出
????注:Linux本身有內存管理方式,但是系統級別的內存優化技術遠不能滿足實際需求,比較流行的內存優化技術包括tcmalloc、ptmalloc、jemalloc等。
? ??內存池的作用:
????1、存放大塊數據
????2、存放數據緩存
5.2 進程/線程池
? ??進程池和線程池的作用:
????1、?避免動態啟動的時間開銷
????2、?使得處理更加單一
????3、?充分利用硬件資源
? ??進程池和線程池的注意事項:
????1、?典型的生產者消費者問題
????2、?注意訪問共享資源存在的競爭
5.3 連接池
????連接池是創建和管理一個連接的緩沖池的技術,這些連接準備好被任何需要它們的線程使用,比如數據庫連接池。
? ??連接池創建的方法:
????1、?預先分配固定數據的連接
????2、?對每一個連接都分配相應的資源
????連接池的作用:
????1、?為創建新連接提速
????2、?可用于集群內部永久性連接
06?緩存
????緩存可以分為本地緩存和分布式緩存。
????本地緩存:編程實現(成員變量、局部變量、靜態變量)。
????分布式緩存:借助Redis、Memcache實現。
????一般系統的寫入請求遠少于讀請求,針對寫少讀多的場景,很適合引入緩存集群。在寫數據庫的時候同時寫一份數據到緩存集群里,然后用緩存承載大部分的讀請求,當緩存中不存在的時候才去數據庫查找,這樣通過緩存集群,就可以用更少的機器資源承載更高的并發。
????緩存的命中率一般能做到很高,而且速度很快,處理能力也強(單機很容易做到幾萬并發),是理想的解決方案。
當然,在使用分布式緩存的時候,需要格外注意處理一致性問題,緩存擊穿,緩存穿透,緩存雪崩等問題。
07?消息隊列
7.1 概述??
????分布式緩存在讀多寫少的場景性能優異,對于寫操作較多的場景可以采用消息隊列集群,它可以很好地做寫請求異步化處理,實現削峰填谷的效果。
????消息隊列能做解耦,在只需要最終一致性的場景下,很適合用來配合做流控。
????業界有很多著名的消息中間件,比如ZeroMQ,rabbitMQ,kafka等。
7.2?特點
??? 1、業務耦合;
????2、最終一致性;
??? 3、廣播;
????4、錯峰與流控。
08?流控
8.1 服務降級
????自動降級:超時、失敗次數、故障、限流
????人工降級:秒殺、雙11大促等
????服務降級要考慮的問題:
????1、核心服務、非核心服務
????2、是否支持降級,降級策略
8.2 應用拆分
????應用拆分原則:
??? 1、業務優先;
??? 2、循序漸進;
??? 3、兼顧技術:重構、分層;
????4、可靠性測試
8.3 限流
????限流的常用處理手段有:計數器、滑動窗口、漏桶、令牌。
? ??1、計數器法
????計數器是一種比較簡單的限流算法,在一段時間內,進行計數,與閥值進行比較,到了時間臨界點,將計數器清0。
????但是,計數器法存在一個時間臨界點的問題。比如,在11:50:00到11:59:59這段時間內沒有用戶請求,然后在12:00:01這一瞬時發出1000個請求,12:00:59又出現1000個請求,在這個臨界點可能會承受惡意用戶的大量請求,甚至超出系統預期的承受。
????2、滑動窗口
????由于計數器存在臨界點缺陷,后來出現了滑動窗口算法來解決。
????滑動窗口的意思是說把固定時間片,進行劃分,并且隨著時間的流逝,進行移動,這樣就巧妙的避開了計數器的臨界點問題。也就是說這些固定數量的可以移動的格子,將會進行計數判斷閥值,因此格子的數量影響著滑動窗口算法的精度。
? ? 3、漏桶算法
????雖然滑動窗口有效避免了時間臨界點的問題,但是依然有時間片的概念,而漏桶算法在這方面比滑動窗口而言,更加先進。
????有一個固定的桶,進水的速率是不確定的,但是出水的速率是恒定的,當水滿的時候是會溢出的。
????4、令牌桶算法
????從某種意義上講,令牌桶算法是對漏桶算法的一種改進,桶算法能夠限制請求調用的速率,而令牌桶算法能夠在限制調用的平均速率的同時還允許一定程度的突發調用。
????在令牌桶算法中,存在一個桶,用來存放固定數量的令牌。算法中存在一種機制,以一定的速率往桶中放令牌。每次請求調用需要先獲取令牌,只有拿到令牌,才有機會繼續執行,否則選擇選擇等待可用的令牌、或者直接拒絕。
09?數據庫高并發
????數據庫高并發分為單機高并發(主要是存儲引擎實現)和集群高并發:
? ??1、單機高并發
????InnoDB存儲引擎采用多版本并發控制技術(MVCC)在不加鎖的情況下,實現并發讀寫,同時通過事務隔離級別控制并發效率。
????2、集群高并發
????數據庫集群高并發主要是通過分庫分表、主備讀寫分離等方法實現的。