高並發葵花寶典


前言

冰凍三尺非一日之寒,葵花寶典也不是一天寫出來的,系統設計也如此,好的架構是不斷演進的。

一般來說能用單塊架構解決的問題,盡量不要采用分布式。

分布式雖然可以提高系統的響應能力,也帶來了更高的復雜性,如果團隊技術人員水平hold不住的話,反而會產生更多問題,例如問題難以定位、系統性能下降、某種業務實現困難或無法實現等問題。

以下內容由偉大的詩人chenqionghe整理,light weight baby~

一、常用指標

響應時間

直觀反應系統快慢,一般控制在200ms以內,超過1s用戶已經能感覺到慢了

並發數

同時處理請求的數目

QPS

每秒查詢請求數

TPS

每秒執行事務數,着重反應寫

二、奪命三高

沒錯,就是高血壓、高血糖和高血脂,開玩笑啦~

高並發

通過設計讓系統能接收更多的用戶並發請求,承擔更大的流量。
一般考查並發數、QPS和TPS。


示例:廬山百龍霸,並發百龍

高性能

一般指服務響應時間快

  • 用戶視角。APP、瀏覽器上能直觀感受快
  • 開發視角。響應延遲低,系統吞吐量大,並發處理能力強
  • 運維視角。基礎設施配置高,CPU多核心,內存容量大


示例:雅典娜之驚嘆,三位黃金聖斗士將自身的究極小宇宙集中在一點進行攻擊

高可用

系統通過設計,減少停工時間,保證服務的高度可用性。
一般會用SLA協議衡量服務可用性,以達到幾個九做為標准
以一年為例,1年 = 365天 = 8760小時

  • 99.9 = 8760 * 0.1% = 8760 * 0.001 = 8.76小時
  • 99.99 = 8760 * 0.0001 = 0.876小時 = 0.876 * 60 = 52.6分鍾
  • 99.999 = 8760 * 0.00001 = 0.0876小時 = 0.0876 * 60 = 5.26分鍾
    SLA提供的可用性越高,那么一年內停機的時間越小

示例:雅典娜之驚嘆,分成不同的小組放招

三、常見招式

分流

本質就是將流量分攤到不同的節點,負載均衡。
常用方法有nginx、haproxy、traefik
舉例:星巴克開分店,增加營業員、擴大面積

緩存


將熱點數據先緩存起來,先從緩存中獲取,提高效率
例如:Redis緩存、Memcached緩存、模板引擎緩存、CPU緩存
舉例:提供超市熱賣攤位,提高顧客購買效率;早餐店先提前把早餐做好,顧客來直接取

隊列

就像訂報紙一樣,先訂閱后送貨,多個客戶可以同時訂閱一種報紙,一個客戶也可以訂閱多種報紙

  • 提高響應速度。
    未處理完成前提前返回,提高響應速度,處理完后再發通知。

  • 系統解耦
    例如一個下單的信息需要同步多個子系統,每個子系統都需要保存訂單的數據的一部分,如果靠訂單服務的團隊維護所有子系統同步,耦合太大,這時候可以通過發布訂閱模型,訂單服務在訂單變化時發送一條消息到一個主題中,所有的下游子系統都訂閱主題,這樣可以每個子系統都可以獲得訂單數據。

  • 緩沖流量,削峰填谷
    為了避免大量的請求沖擊后端服務,可以使用消息隊列暫存請求,后端服務按照自己的處理能力,從隊列中消費,例如秒殺、埋點場景。

簡單地說,就是業務上游隊列緩沖限速發送,業務下游隊列緩沖限速執行

秒條場景,一般處理兩種方式:
加鎖。比如golang包中的mutex,也可以利用redis本身操作原子性的特點
寫入消息隊列。在消息隊列中做減庫存的操作

舉例:去海盜蝦飯吃飯,先結賬,做好了給你端過來

CDN

CDN(Content Delivery Network)官方定義叫內容分發網絡。
簡單的說就是一種緩存,原理是將靜態的資源分發到多個地埋位置服務器上,最終達到就近獲取數據的效果,例如北京地區訪問北京的數據,海南訪問海南的。
當然,這也不用我們自己開發,例如阿里雲、七牛雲等知名雲廠商都提供了CDN服務。
一般使用就是設置CDN回源更新數據的地址,將服務域名解析到雲廠商返回的CNAME上。

舉例:京東購買東西,發貨都直接從最近的倉庫發貨,只有倉庫沒貨了才會到源頭取貨(回源)

池化

一般連接的創建是比較耗資源和時間,一般我們可以使用連接池來提升效率,這就是傳說中的池化技術,常見的有數據庫連接池、線程池。
設定空閑連接數和最大連接數,步驟一般如下:

  1. 當前連接數小於空閑連接數,創建
  2. 連接池中有空閑連接直接使用
  3. 沒有空閑連接,當前連接數小於最大連接數,創建
  4. 達到或超過最大連接數,按設定超時時間等待舊連接釋放,超時拋出錯誤

本質都是空間換時間,一般創建的連接對象會放到一個隊列中。

擴容

  • 垂直擴容
    升配置,例如加CPU核心、加內存、改為IO優化型存儲

    示例:倍化之術

  • 水平擴容
    直接加機器,多多益善

    示例:影分身之術

熔斷

當某服務調用的時候,如果返回錯誤或者超時次數超過一定閾值后,后續請求不再發送直接返回錯誤
舉例:就像電路的熔斷器一樣,電流過載,自動斷開電路。
開源方案有:hystrix、traefik、istio

限流

通過限制到達系統的並發請求數量,保證系統能正常響應部分用戶的請求。超過限制的流量,通過拒絕服務的方式保證整體系統的可用性。
舉例:十一假期去莫高窟旅游,景點只放出有限的門票,門票賣完,新來的客戶不再接待。
可以在系統中埋下限流的代碼,例如可以使用golang的緩沖channel實現。

降級

就像被沙加剝奪了五感一樣

例如雙十一的時候,打開淘寶,會發現界面上的信息少了很多,其實這就是一種降級,關閉或者拒絕很多不重要的功能,節省服務器資源抵御高並發大流量。

分層

好處:分工明確,方便復用、容易針對層做擴展。
這個分層,可以指代碼架構,也可以指服務架構,一般不跨層調用

  • MVC
    控制器(C)調用模型(M)取數據,再通過(V)渲染視圖。
    業務邏輯一般寫到模型中進行復用,但是可能會帶來的是模型之間的職責划分不明確。
    所以一般還會在其中加入Service層,使Model模型不再存放業務邏輯。

  • Web、Service、Dao

    • Web:表現層。可以簡單理解成Controller和View
    • Service:業務邏輯層。業務邏輯都封裝到這一層,這一層直接調用Dao取數據
    • Dao:數據訪問層。負責訪問數據庫,最常見的是AR模型或者ORM

    可以簡單理解成MVC加了一層Service,Controller直接調用Service,Service再調用Model

  • Web、Service、Manager、Dao
    在Service和Dao之間加了一層Manager,抽取service層之間的共同邏輯。

部署分級

根據優先級的高低將服務部署到不同的物理機上,可以通過K8S的label選擇最終部署的節點

舉例:六道仙人給尾獸分等級,分別分配給實力不同的忍之國

日志監控

  • 日志追蹤。
    使用ELK或者阿里雲日志服務。請求和打日志傳遞requestId,查詢根據requestId檢索請求相關的所有日志
  • 調用鏈追蹤.
    開源方案Zipkin,Jaeger 。核心是通過TranceId和SpanId追蹤每次調用
  • Prometheus監控
    把需要監控的指標存儲到prometheus中,通過grafanan展示
  • Sentry監控
    統一搜集采集異常日志,針對500這種錯誤到sentry后台查詢,比較方便定位問題

查詢優化

簡單地說是可以走索引,像射箭一樣直中目標

  • 優化sql索引。分析sql執行效率,通過加索引優化
  • 引入Elasticsearch。提高搜索效率,降低模糊搜索給數據庫帶來的壓力。

讀寫分離

將讀請求和寫請求分推到不同的實例,例如MySQL讀寫分離、Redis讀寫分離
MySQL主從分離核心是binlog,主庫將binlog寫入relay log文件,從庫過來拉取。

主從同步容易遇到延遲問題,例如主庫已經寫入了,從庫查詢的還是老數據,一般會通過以下方式解決:

  1. 直接讀主庫
  2. 更新主庫前寫緩存,讀緩存
  3. 直接將更新的數據傳遞,不查庫

分庫分表

一般會配合服務一起拆分

  • 垂直拆分。
    專門的服務使用專門的庫。例如一個購買流程,可以拆分為商品庫、訂單庫。
  • 水平拆分。
    例如將users拆成10個庫,users0、users1...users9,根據某個字段的取模存放到不同的庫。

缺點:

  • 無法做join
  • 統計數量是個問題
  • 不能再使用事務


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM