<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一次線上事故,我頓悟了異步的精髓 !

          共 2448字,需瀏覽 5分鐘

           ·

          2022-08-09 04:31

          大家好,我是魚皮。前段時間,我的一個朋友在高并發(fā)的生產(chǎn)環(huán)境中發(fā)生了一次事故,我認為這次事故的場景非常具備典型性 。而在高并發(fā)的場景下,異步是一個極其重要的優(yōu)化方向。

          所以我分享的這篇文章,想和大家深入探討該場景的架構(gòu)優(yōu)化方案。希望大家讀完之后,可以對異步有更深刻的理解。

          1 業(yè)務場景

          老師登錄教研平臺,會看到課程列表,點擊課程后,課程會以視頻的形式展現(xiàn)出來。

          6235c56d4f670ee9357462e62e1342f6.webp

          訪問課程詳情頁面,包含兩個核心動作:

          1. 讀取課程視頻信息 :

            從緩存服務器 Redis 獲取課程的視頻信息 ,返回給前端,前端通過視頻組件渲染。

          2. 寫入課程觀看行為記錄 :

            當教師觀看視頻的過程中,瀏覽器每隔3秒發(fā)起請求,教研服務將觀看行為記錄插入到數(shù)據(jù)庫表中。而且隨著用戶在線人數(shù)越多,寫操作的頻率也會指數(shù)級增長。

          上線初期,這種設計運行還算良好,但隨著在線用戶的增多,系統(tǒng)響應越來越慢,大量線程阻塞在寫入視頻觀看進度表上的 Dao 方法。上。

          首先我們會想到一個非常直觀的方案,提升寫入數(shù)據(jù)庫的能力

          1. 優(yōu)化 SQL 語句;
          2. 提升 MySQL 數(shù)據(jù)庫硬件配置 ;
          3. 分庫分表。

          這種方案其實也可以滿足我們的需求,但是通過擴容硬件并不便宜,另外寫操作可以允許適當延遲和丟失少量數(shù)據(jù),那這種方案更顯得性價比不足。

          那么架構(gòu)優(yōu)化的方向應該是:“減少寫動作的耗時,提升寫動作的并發(fā)度”, 只有這樣才能讓系統(tǒng)更順暢的運行。

          于是,我們想到了第二種方案:寫請求異步化

          • 線程池模式
          • 本地內(nèi)存 + 定時任務
          • MQ 模式
          • Agent 服務 + MQ 模式
          2 線程池模式

          2014年,筆者在某旅行網(wǎng)負責紅包系統(tǒng)相關工作。運營系統(tǒng)會調(diào)用紅包系統(tǒng)給特定用戶發(fā)送紅包,當這些用戶登錄 app 后,app 端會調(diào)用紅包系統(tǒng)的激活紅包接口 。

          激活紅包接口是一個寫操作,速度也比較快(20毫秒左右),接口的日請求量在2000萬左右。

          應用訪問高峰期,紅包系統(tǒng)會變得不穩(wěn)定,激活接口經(jīng)常超時,筆者為了快速解決問題,采取了一個非常粗糙的方案:

          "控制器收到請求后,將寫操作放入到獨立的線程池中后,立即返回給前端,而線程池會異步執(zhí)行激活紅包方法"。

          當時按照這種粗糙的方法優(yōu)化后,紅包系統(tǒng)非常穩(wěn)定,再也沒有出現(xiàn)接口響應超時的問題。

          回到教研的場景,見下圖,我們也可以設計類似線程池模型的方案:

          0d50fcfd2e316457f9e15b677ac0ec7d.webp

          使用線程池模式,需要注意如下幾點:

          1. 線程數(shù)不宜過高,避免占用過多的數(shù)據(jù)庫連接?;
          2. 需要考慮評估線程池隊列的大小,以免出現(xiàn)內(nèi)存溢出的問題。
          3 本地內(nèi)存 + 定時任務

          開源中國統(tǒng)計瀏覽數(shù)的方案非常經(jīng)典。

          用戶訪問過一次文章、新聞、代碼詳情頁面,訪問次數(shù)字段加 1 , 在 oschina 上這個操作是異步的,訪問的時候只是將數(shù)據(jù)在內(nèi)存中保存,每隔固定時間將這些數(shù)據(jù)寫入數(shù)據(jù)庫。

          79504e540ade45d708b6d12553703c0a.webp

          示例代碼如下:

          6576766eecf418aaace1c9a6f964069a.webp

          我們可以借鑒開源中國的方案 :

          1. 控制器接收請求后,觀看進度信息存儲到本地內(nèi)存 LinkedBlockingQueue 對象里;

          2. 異步線程每隔1分鐘從隊列里獲取數(shù)據(jù) ,組裝成 List 對象,最后調(diào)用 Jdbc batchUpdate 方法批量寫入數(shù)據(jù)庫;

          3. 批量寫入主要是為了提升系統(tǒng)的整體吞吐量,每次批量寫入的 List 大小也不宜過大 。

          這種方案優(yōu)點是:不改動原有業(yè)務架構(gòu),簡單易用,性能也高。該方案同樣需要考慮內(nèi)存溢出的風險。

          4 MQ 模式

          很多同學們會想到 MQ 模式 ,消息隊列最核心的功能是異步解耦,MQ 模式架構(gòu)清晰,易于擴展。

          b7bc9c2fa45a0b816534c1c3fceebdaf.webp

          核心流程如下:

          1. 控制器接收寫請求,將觀看視頻行為記錄轉(zhuǎn)換成消息 ;
          2. 教研服務發(fā)送消息到 MQ ?,將寫操作成功信息返回給前端 ;
          3. 消費者服務從 MQ 中獲取消息 ,批量操作數(shù)據(jù)庫 。

          這種方案優(yōu)點是:

          1. MQ 本身支持高可用和異步,發(fā)送消息效率高 , 也支持批量消費;
          2. 消息在 MQ 服務端會持久化,可靠性要比保存在本地內(nèi)存高;

          不過 MQ 模式需要引入新的組件,增加額外的復雜度。

          5 Agent 服務 + MQ 模式

          互聯(lián)網(wǎng)大廠還有一種常見的異步的方案:Agent 服務 + MQ 模式。

          71998d9cbba4cba4d9fbbeb3dbe2e5e5.webp

          教研服務器上部署 Agent 服務(獨立的進程) , 教研服務接收寫請求后,將請求按照固定的格式(比如 JSON )寫入到磁盤中,然后給前端返回成功信息。

          Agent 服務會監(jiān)聽文件變動,將文件內(nèi)容發(fā)送到消息隊列 , 消費者服務獲取觀看行為記錄,將其存儲到 MySQL 數(shù)據(jù)庫中。

          這種方案最大的優(yōu)點是:架構(gòu)分層清晰,業(yè)務服務不需要引入 MQ 組件。

          筆者原來接觸過的性能監(jiān)控平臺,或者日志分析平臺都使用這種模式。

          6 總結(jié)

          學習需要一層一層遞進的思考。

          第一層:什么場景下需要異步

          • 大量寫操作占用了過多的資源,影響了系統(tǒng)的正常運行;
          • 寫操作異步后,不影響主流程,允許適當延遲;

          第二層:異步的外功心法

          本文提到了四種異步方式:

          • 線程池模式

          • 本地內(nèi)存 + 定時任務

          • MQ 模式

          • Agent 服務 + MQ 模式

          它們的共同特點是:將寫操作命令存儲在一個池子后,立刻響應給前端,減少寫動作的耗時。任務服務異步從池子里獲取任務后執(zhí)行。

          第三層:異步的本質(zhì)

          在筆者看來,異步是更細粒度的使用系統(tǒng)資源的一種方式

          在教研課程詳情場景里,數(shù)據(jù)庫的資源是固定的,但寫操作占據(jù)大量數(shù)據(jù)庫資源,導致整個系統(tǒng)的阻塞,但寫操作并不是最核心的業(yè)務流程,它不應該占用那么多的系統(tǒng)資源。

          不能為了異步而異步,無論是使用線程池,還是本地內(nèi)存 + 定時任務 ,亦或是 MQ ,對數(shù)據(jù)庫資源的使用都需要在合理的范圍內(nèi),否則異步就達不到我們想要的效果。


          以上就是本期分享了。

          最后,歡迎加入??魚皮的編程知識星球(點擊了解詳情),和大家一起交流學習編程,向魚皮和大廠同學 1 對 1 提問、幫你制定學習計劃不迷茫、跟著魚皮直播做項目(往期項目可無限回看)、領取魚皮原創(chuàng)編程學習/求職資料等。最近秋招開始了,星球內(nèi)也會幫大家規(guī)劃求職進度、完善簡歷和項目。


          2d168f1553e74d1e0c2aa65a20da3ca1.webp


          往期推薦

          我竟然堅持半年了!

          我做了個很帥的網(wǎng)站!

          一夜成名的航班追蹤網(wǎng)站,什么來頭?

          該死的單元測試,寫起來到底有多痛?

          Vue 無虛擬DOM模式即將到來

          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  爱插综合网| 日本操操操BBB | 无码专区日韩 | 中文字幕一区二区三区四区50岁 | 亚洲国产精品18久久久久久 |