高併發高可用系統的一些胡亂思考

原文鏈接: 何曉東 博客

個人理解高併發系統主要在於:機器資源的合理分配和性能的壓榨,代碼質量,及維護高併發系統在請求峯值的時候,系統中有機器宕機時整個系統的可用性。核心是提高吞吐,降低響應時間。

隨意想

還有幾個觀點是:高併發技術可以有,但是很多公司沒有高併發場景。越是沒有高併發場景的公司越願意問高併發的問題,是爲了考察面試者對於行業尖端技能的學習還是爲了壓價?而有高併發場景的公司一般很在乎基礎,基礎好的人寫出來的代碼比爛代碼性能強一點的話,併發時會嚴重放大提升的這一點性能。

至於在有併發場景之前的優化網站性能,多數情況會依賴:1. 前端資源 CDN 化,公用的資源編譯壓縮,同時使用瀏覽器自身緩存,提升資源加載速度,也減少訪問一個頁面給此域名帶來很多的請求。 2. 優化 SQL 操作,95%+ 的問題是 sql 優化可以提升的,對應也有代碼中的魔性操作,帶來的執行效率的問題。

高併發依賴於場景和邏輯

不一定每個場景都會產生高併發,不要爲了高併發而盲目的設計,過度設計帶來的問題遠比意料之外的高併發要多很多,依賴於具體場景和行爲進行分析,一個購物類網站,搶購場景,會觸發很多的讀取商品詳情,計算庫存等操作,而且不需要每個請求都到達支付頁面,也不會在網站主頁帶來很多的請求,所以需要針對搶購場景進行優化,而不是巨大的支付流程進行優化,當然商品數量多和用戶多的情況,才需要也優化一下支付流程。

拋開場景,不談流量的盲目高併發設計,一般是過度設計,未來維護臃腫而複雜的代碼會懲罰你當初的過度設計。

突如其來的高併發

基本是被人刷了,或者比預估的情況要多了幾倍,纔有這種情況,前者可能性很大,最近這兩年的金融網站,區塊鏈,xx幣網站,基本會被羊毛黨盯上,沒做好訪問防作弊,或者被對手 ddos 攻擊,都會造成高併發中網站癱瘓,清洗流量一般就可以的,不要讓辣雞流量貫穿整個業務。高併發會帶來網站請求慢,但網站請求慢不一定是高併發了,對症下藥。

如果是網紅帶貨什麼的,給網站帶來高併發了,這種情況下可以在提前流量上做些手腳,例如:1. 用消息隊列排隊流量,例如猴王網站的搶購 2. 採用一些高端點的驗證碼,讓一些秒殺搶購的機器號被過濾出去,儘量不影響真實用戶的搶購結果 3. 分層過濾,例如靜態資源放在 CDN 上,NGINX 層面使用自身的緩存,根據路由緩存基礎數據,其他動態數據再讀寫數據庫,而不是每個請求都經過整體的業務,這樣帶來的壓力太大了,而且也不值得。

併發中的整體項目穩定性

可以將高併發的業務部分分離到單獨的服務器。這種情況下能夠避免這部分業務帶來機器性能的消耗,從而影響整個項目的穩定性,這樣的結果不太好的。也可以預先將熱數據放到緩存中,提高讀寫效率,也能讓 MySQL 比較穩定,一般情況下能有高併發的網站,數據量也不少,舉例某個電商網站,可能有 100w 商品數據,但大家搶購的是今天熱推的 10 個商品,將這十個數據提取放到緩存中,而不是每次去數據庫中查詢,當然 MySQL 設置合理的話,自身的 buffer pool 也能搞定這些熱數據緩存。這樣相當於將這 10 條數據隔離出來,而不是影響到整體數據。關於熱點數據的發現,還有一些高端的是從 NGINX 訪問日誌層面實時分析,據說淘寶這種是這樣的,實時發現訪問很多的路由,分析路由獲取到對應的商品數據,放到緩存中,減輕服務器壓力。

穩定性不光存在於業務機器層面,也可能是網絡寬帶不夠,或者程序在磁盤寫日誌的時候遇到瓶頸,或者內存不夠,導致可用緩存空間很小。這些在測試和計算層面需要注意的問題,也會影響整體穩定性和性能的,應該提前解決。例如秒殺系統需要關注 CPU,併發讀需要關注緩存,靜態資源多的也需要考慮寬帶。

預先測試

簡單可以是壓測關鍵業務部分,簡單的查詢一般不會帶來問題,這個頁面的靜態資源太多,同時都在統一個域名下的話,相當於在現有併發的數量上加了更多,這非常不利,對於瀏覽器的加載也是不利的,簡單業務也會體驗很差。壓力測試應當遵循慢慢提升流量的方式,併發量和響應時間並不是等比例上漲的,慢慢提升併發量的測試,會展示代碼的瓶頸部分在哪,然後在去解決和提升。測試也可以

在基礎的併發測試之外,還有在正是服務器上的全鏈路壓力測試,爲了防止和真實數據衝突,可以將請求中加上額外的標記,或者針對特定的用戶帳號測試,在數據中體現這部分額外標記,測試完畢之後將數據刪除。

同時,不要高併發的主要業務一直佔用機器的 100% 的運算能力,這樣整體邏輯和請求支持已經到了極限,基本再高一點就會造成問題,應該儘量讓業務只佔用機器 60-70% 的運算能力,留出一部分的餘地,防止意外。

安全及備用方案

  1. 從 NGINX 層面限制單個 IP 單位時間內請求頻率和次數,屏蔽掉機器刷的可能性,從而不影響正常訪問。 2. 切記高併發 + 高可用不可以用單點系統,例如不能因爲熱數據少而就用一臺 Redis 服務器,或者更狠的直接本機緩存,一旦系統崩潰,相當於觸發連鎖反應,連保存現場和恢復都很難。 3. 提前設計兜底方案 ① 降級,例如商品詳情頁面不展示推薦商品,或者減少推薦商品展示數量等, ② 限流,不讓更多流量涌入,能減少很多壓力 ③ 過載臨界點拒絕服務,這個是最壞的情況,直接阻斷壓垮系統的最後一個流量。

參考鏈接:

  1. 構建一個高性能、高可用的大型分佈式網站
  2. 關於高併發 - 知乎專欄
  3. 如何獲得高併發經驗 - 知乎問答
  4. sf 我們討論高併發的時候在討論什麼
  5. 極客時間 - 設計一個高併發系統 -> 用我的碼去購買
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章