面向魯棒的系統設計
前言
- 本來打算叫做面向異常的程式設計的,後來覺得可能多的是系統健壯性方面,於是改名面向魯棒的系統設計,所謂魯棒,魯棒是Robust的音譯,也就是健壯和強壯的意思。它是在異常和危險情況下系統生存的關鍵。
- 平時在做業務系統的時候,尤其是最近一年多接觸的超複雜系統,發現處理線上問題所佔的時間越來越多,總結發現,其實這些問題大都是之前欠下的債,至於為啥欠債,大多數情況下迫於專案或者日常的時間壓力,很多設計從簡,業務流程考慮主流程和分支流程,異常流程關注的少,不管三七二十一,功能先上線再說,如此便導致了惡性迴圈。
- 由此,我們可以有的應對方案是啥呢,後面的專案,肯定也會是時間壓力大的,那隻能提升我們自身處理異常的能力了,也就是說在系統設計或者方案考慮的時候,就規避掉,提升應對經驗,這樣在同樣的時間裡面,就能夠遊刃有餘,編寫出更高質量的程式碼,進入良性迴圈階段。
解決方案探索
- 大多數的新手程式設計師,由於編碼經驗的缺失,導致在程式碼的保護方面做的不好,隨著後續編碼經驗的積累以及採坑次數的增加,慢慢的會更多關注在健壯性方面;
- 分享部分典型的案例,抽象一下,學習別人失敗的教訓,舉一反三,來規避問題;
抽象的解決方案描述
-
遠端資源的呼叫,務必考慮失敗或者超時的邏輯
; -
業務邏輯的測試,多多模擬異常的邊界情況
; -
資料獲取類的介面,需要評估目前的資料量,後續的增長情況,以及極端情況下的量大小
; -
列表類的介面或者資料展示,需要考慮資料的極限情況,最大是多少,並做好保護
; -
批量的資料,務必需要考慮異常情況,部分失敗了怎麼辦
;
典型案例
-
本地快取,載入失敗,之後應用系統啟動
- java local cache在高併發系統中,使用的較多,把熱點的資料或者後設資料儲存在JVM的heap區,從而實現低延遲,但是這裡就涉及到快取資料的載入了;
- 常用的資料載入方案,一種是應用啟動的時候,全部載入所有的資料,之後有增量變更的時候,再增量更新;另外一種是啟動的時候不載入,在資料第一次訪問的時候載入這個資料;
- 這兩種方式各有優劣,但是假如選擇了第一種,就需要在邏輯裡面考慮,假如快取資料載入失敗了,怎麼辦,是應用系統直接啟動失敗,還是程式碼邏輯裡面冗餘懶載入的機制,如果不考慮,又一個坑留下了;
-
分散式快取和資料庫中的資料一致性考慮
- 目前網際網路級的系統,快取基本上是架構上不可或缺的,引入快取,必然就會面臨資料一致性問題,舉個例子,加入同一份資料,在DB和快取中都有,這時候使用者在頁面操作,變更資料,需要變更快取和DB,需要同時生效,如果update 的sql執行成功,之後快取變更的時候超時了導致變更失敗,這時候,整體應該返回使用者失敗,然後DB的資料回滾掉。
- 如果是沒有經驗的開發,可能就DB更新,然後快取更新,沒有針對快取更新失敗或者超時做邏輯處理,本地值系統功能邏輯缺失導致;
-
業務操作和資料庫持久化以及訊息傳送的一致性考慮
- 業務系統,在考慮非同步解耦的時候,會引入訊息系統,這時候面臨了一個問題,就是業務操作和訊息系統的一致性問題;
- 業務操作和訊息的傳送,要能夠滿足事務的特性,例如藉助二階段提交來實現,然後訊息系統來進行重試,從而實現最終一致性的要求;
-
批量更新資料庫的順序問題導致的死鎖
- 假如這裡有個方法,是List資料的更新,在併發情況下,如果更新的SQL不做排序,會導致死鎖問題,這時候需要按照唯一主鍵,例如id來做排序,從而保證鎖佔用的時候的順序性;
- 至於為啥會有死鎖問題,假如兩個呼叫,含有相同的資料,例如都含有A和B,因為批量update佔鎖的時候,是行級佔用,第一個執行緒是A-B順序,第二個執行緒是B-A順序,第一個執行緒佔了A,第二個執行緒佔了B,然後,然後就死鎖了;
-
頁面點選操作,可能涉及到非常複雜的業務邏輯,是否考慮非同步化,引入排隊機制
- 舉個例子,點選一個確認按鈕,背後很多業務邏輯,這時候需要使用者等待的時間比較長;
- 如果存在少量資料和大量資料共同存在,切大資料量是常態的情況下,可以考慮非同步化操作;
- 使用者點選之後,儲存任務在進行中的狀態,然後後臺多執行緒處理,處理完了之後,回寫狀態,頁面重新整理後看到最新的結果,如果不需要使用者重新整理就能看到結果,可以在頁面做長連線或者ajax輪訓;
-
更新資料,例如更新十條,第六條出錯了,是回滾還是繼續處理
- 批量操作,正常流程沒有問題,一下子全部成功,但是假如其中的一條出現錯誤;
- 兩種方案,一種是所有的資料都回滾,然後提示使用者修改資料,重新提交,另外一種就是成功的提交,失敗的記錄下來,讓使用者重試失敗的資料,但是失敗的邏輯一定要有;
-
頁面資料載入多個區塊的資料,且部分割槽塊獲取資料的介面高延遲
- 同步載入的時候,整個頁面載入的速度會慢很多,所以在做資料載入設計的時候,就要區分掉;
- 區塊可以修改為非同步ajax來進行載入資料;
-
資料匯出功能,如果是非常少的資料匯出,則直接匯出即可,但是資料量大,就會面臨各種問題
- 資料讀取的時候,如果多於特定的量,是否可以分頁或者多執行緒載入;
- 匯出資料的上限限制,如果沒有上限,可能出現幾百萬的資料,使用者點選導致,由於http請求的超時機制,使用者可能會重複點選,此時伺服器和資料庫的壓力會很大;
- 資料回寫,除了直接返回之外,是否可以寫檔案,然後直接提供給使用者需要下載的檔案連結;
- 平時遇到的問題大多數是,系統剛剛上線,業務資料比較少,功能能夠正常,但是隨著業務發展,資料越來越多,導致的問題就是無法下載下來,而如果沒有做上面的優化或者保護的話,這個功能使用就會出現異常;
相關文章
- 資訊系統設計三個面向
- 張曄:面向統計研究的R程式設計程式設計
- 基於MCU的系統從面向使用者的設計角度獲益
- 模型攻擊:魯棒性聯邦學習研究的最新進展模型聯邦學習
- 如何編寫高質量的函式 -- 命名/註釋/魯棒篇函式
- XPROG: 簡單實用的魯棒優化(RO, DRO)程式語言優化
- PHP 的面向方面程式設計PHP程式設計
- 誰是最棒的容器作業系統?作業系統
- 面向介面程式設計程式設計
- 面向系統管理員的 Bash 指南
- XPROG: 簡單實用的魯棒最佳化(RO, DRO)程式語言
- 利用魯棒控制實現深度強化學習駕駛策略的遷移強化學習
- SCRDet——對小物體和旋轉物體更具魯棒性的模型模型
- 程式設計思想 面向切面程式設計程式設計
- 面向資料的程式設計 · Laurent程式設計
- 面向sql程式設計的探索之路SQL程式設計
- 系統設計面試參考-設計Spotify系統面試
- 《風暴英雄》裡那些超棒的遊戲設計遊戲設計
- 系統設計:設計Spotify
- AOP 面向切面程式設計程式設計
- 面向架構程式設計架構程式設計
- AOP(面向切面程式設計)程式設計
- 面向協議程式設計協議程式設計
- 面向切面程式設計AOP程式設計
- 面向方面的程式設計程式設計
- 面向指標程式設計指標程式設計
- 面向系統管理員的容器手冊
- 系統架構設計之-任務排程系統的設計架構
- 設計模式之面向切面程式設計AOP設計模式程式設計
- Android AOP面向切面設計程式設計Android程式設計
- Laravel 回撥系統的設計 Cybereits.com 白名單系統的設計Laravel
- 面向大規模佇列,百萬併發的多優先順序消費系統設計佇列
- aop面向切面程式設計的實現程式設計
- Java中的面向切面程式設計(AOP)Java程式設計
- 面向演算法的架構設計演算法架構
- Swift中的面向協議程式設計Swift協議程式設計
- 面向JavaScript的SOLID設計原則JavaScriptSolid
- 面向.Net程式設計師的dump分析程式設計師