【數據密集型系統設計】軟件系統的可靠性、可伸縮性、可維護性

文章目錄

  • 一. 數據密集型程序的特點以及遇到的問題
  • 二. 可靠性 : 即使出現問題,也能繼續正確工作
    • 1 硬件故障
    • 2. 軟件錯誤
    • 3. 人為錯誤
  • 二. 可伸縮性
    • 1. 描述負載與推特的例子
    • 2. 描述性能-延遲和響應時間
    • 3. 應對負載的方法
  • 四. 可維護性
    • 1. 可操作性:人生苦短,關愛運維
    • 2. 簡單性:管理復雜度
    • 3. 可演化性:擁抱變化

本文討論了軟件系統的可靠性,可伸縮性和可維護性。

  • 可靠性(Reliability) 指高可用:及時發生故障(人為、bug、硬件服務)也能提供服務。一般高可用通過主備的概念去實現;

  • 可伸縮性(Scalability) 負載增加的情況下也有保持性能的策略,一般進行橫向拓展;

  • 可維護性(Maintainability):這里強調抽象降低復雜度,并易于修改和適應新的應用場景。

?

一. 數據密集型程序的特點以及遇到的問題

現今很多應用程序都是 數據密集型(data-intensive) 的,而非 計算密集型(compute-intensive) 的。因此 CPU 很少成為這類應用的瓶頸,更大的問題(是內存)通常來自數據量、數據復雜性、以及數據的變更速度。

?

標準組件提供了應用的能力
數據密集型應用通常由標準組件構建而成,標準組件提供了很多通用的功能。例如,許多應用程序都需要:

  1. 存儲數據,以便自己或其他應用程序之后能再次找到 (數據庫,即 databases
  2. 加快讀取速度(緩存,即 caches
  3. 允許用戶按關鍵字搜索數據,或以各種方式對數據進行過濾(搜索索引,即 search indexes
  4. 向其他進程發送消息,進行異步處理(流處理,即 stream processing
  5. 定期處理累積的大批量數據(批處理,即 batch processing

?

使用多個組件的數據系統架構

應用代碼將不同功能的工具縫合起來來一起服務,服務的接口想客戶端隱藏這些實現細節。這個復合系統會有特定的保證:例如:緩存在寫入時會作廢或更新,以便外部客戶端獲取一致的結果。

應用架構的樣子:

在這里插入圖片描述

?

設計數據系統或服務時會遇到如下通用的問題:

  1. 當系統出問題時,如何確保數據的正確性和完整性?
  2. 當部分系統退化降級時,如何為客戶提供始終如一的良好性能?
  3. 當負載增加時,如何擴容應對?
  4. 什么樣的 API 才是好的 API?

?

這里我們討論大多數系統中遇到的共性問題:

  • 可靠性(Reliability):

  • 可伸縮性(Scalability):面對數據、流量導致的內存增長,復雜性導致的可伸縮性變差有合理的辦法應對系統的增長(數據量、流量、復雜性)。

  • 可維護性(Maintainability):

?

二. 可靠性 : 即使出現問題,也能繼續正確工作

人們對可靠軟件的典型期望包括

允許用戶犯錯、系統能防止未經授權的訪問和濫用、在預期的負載和數據量下,性能滿足要求。

1 硬件故障

硬盤的 平均無故障時間(MTTF, mean time to failure) 約為 10 到 50 年。因此從數學期望上講,在擁有 10000 個磁盤的存儲集群上,平均每天會有 1 個磁盤出故障。
?

增加單個硬件的冗余度來減少系統故障率:

為了減少系統的故障率,第一反應通常都是增加單個硬件的冗余度,例如:磁盤可以組建 RAID,服務器可能有雙路電源和熱插拔 CPU,數據中心可能有電池和柴油發電機作為后備電源,某個組件掛掉時冗余組件可以立刻接管。這種方法雖然不能完全防止由硬件問題導致的系統失效,但它簡單易懂,通常也足以讓機器不間斷運行很多年。

?

多節點的高可用:

多節點的設計就是優先考慮 靈活性(flexibility)彈性(elasticity),而不是單機可靠性。

?

2. 軟件錯誤

比起不相關的硬件故障往往可能造成更多的 系統失效

  1. 失控進程會用盡一些共享資源,包括 CPU 時間、內存、磁盤空間或網絡帶寬。
  2. 系統依賴的服務變慢,沒有響應,或者開始返回錯誤的響應。
  3. 級聯故障,一個組件中的小故障觸發另一個組件中的故障,進而觸發更多的故障

監控是有必要的

如果系統能夠提供一些保證(例如在一個消息隊列中,進入與發出的消息數量相等),那么系統就可以在運行時不斷自檢,并在出現 差異(discrepancy) 時報警。

?

3. 人為錯誤

盡管人類不可靠,但怎么做才能讓系統變得可靠?最好的系統會組合使用以下幾種辦法:

  1. 將人們最容易犯錯的地方與可能導致失效的地方 解耦(decouple)。比如提供一個功能齊全的非生產環境 沙箱(sandbox),使人們可以在不影響真實用戶的情況下,使用真實數據安全地探索和實驗。
  2. 確定測試邊界
  3. 快速回滾配置變更,分批發布新代碼
  4. 遙測(telemetry):配置詳細和明確的監控,比如性能指標和錯誤率。監控可以向我們發出預警信號,并允許我們檢查是否有任何地方違反了假設和約束。當出現問題時,指標數據對于問題診斷是非常寶貴的。

?

二. 可伸縮性

可伸縮性(Scalability) 是用來描述系統應對負載增長能力的術語。

系統今天能可靠運行,并不意味未來也能可靠運行。服務 降級(degradation) 的一個常見原因是負載增加,例如:系統負載已經從一萬個并發用戶增長到十萬個并發用戶,或者從一百萬增長到一千萬。

1. 描述負載與推特的例子

描述負載的方面,要注意最佳選擇取決于系統架構與業務的流量

  1. 可能是每秒向 Web 服務器發出的請求
  2. 數據庫中的讀寫比率
  3. 聊天室中同時活躍的用戶數量
  4. 緩存命中率或其他東西

為了使這個概念更加具體,我們描述推特的例子。推特的兩個主要業務是:

  • 發布推文: 用戶可以向其粉絲發布新消息(平均 4.6k 請求 / 秒,峰值超過 12k 請求 / 秒)。
  • 主頁時間線: 用戶可以查閱他們關注的人發布的推文(300k 請求 / 秒)。

這里的一個需求是:當博主發布新的作品時,給關注他的人發送推文的邏輯。

方法說明
方法1發布推文時,只需將新推文插入全局推文集合即可。當一個用戶請求自己的主頁時間線時,首先查找他關注的所有人,查詢這些被關注用戶發布的推文并按時間順序合并。
方法2維護消息隊列,當發布新的博文時,提前給每個關注者發送到主頁緩存中。所以讀取開銷小,因為寫入時已經做了這部分工作。 因為寫入時做更多的工作,寫出時做更少的工作,這樣查詢時會更快。

?

方法1,2的優劣

  1. 推特的第一個版本使用了方法 1,但系統很難跟上主頁時間線查詢的負載。所以公司轉向了方法 2,方法 2 的效果更好,因為發推頻率比查詢主頁時間線的頻率幾乎低了兩個數量級。
  2. 方法 2 的缺點是,發推現在需要大量的額外工作。平均來說,一條推文會發往約 75 個關注者,所以每秒 4.6k 的發推寫入,變成了對主頁時間線緩存每秒 345k 的寫入。但這個平均值隱藏了用戶粉絲數差異巨大這一現實,一些用戶有超過 3000 萬的粉絲,這意味著一條推文就可能會導致主頁時間線緩存的 3000 萬次寫入!及時完成這種操作是一個巨大的挑戰 —— 推特嘗試在 5 秒內向粉絲發送推文。

要根據負載來選擇方案,不能一概而論

  • 這里需要考慮的是,因為每個用戶粉絲數的分布決定了扇出負載,而且需要在一定的時間內扇出,這里對系統的伸縮性(通過添加機器來分擔負載?)也提出了要求,所以方法1,2不能一概而論。
  • 雖然在查詢速度上慢,但方法1的扇出負載明顯比方法2小,所以找到用戶可接受的加載時間是需要權衡的。

?
最終的方案:
現在已經穩健地實現了方法 2,推特逐步轉向了兩種方法的混合。

  1. 大多數用戶發的推文會被扇出寫入其粉絲主頁時間線緩存中。
  2. 少數擁有海量粉絲的用戶(即名流)會被排除在外。當用戶讀取主頁時間線時,分別地獲取出該用戶所關注的每位名流的推文,再與用戶的主頁時間線緩存合并,如方法 1。

這樣就規避了這些名流帶來的巨大扇出負載。

?

2. 描述性能-延遲和響應時間

一旦系統的負載被描述好,就可以研究當負載增加會發生什么。

  • 增加負載參數并保持系統資源(CPU、內存、網絡帶寬等)不變時,系統性能將受到什么影響?
  • 增加負載參數并希望保持性能不變時,需要增加多少系統資源?

這兩個問題都需要性能數據,所以讓我們簡單地看一下如何描述系統性能。

  • 對于 Hadoop 這樣的批處理系統,通常關心的是 吞吐量(throughput),即每秒可以處理的請求、或者在特定規模數據集上運行作業的總時間。
  • 對于在線系統,通常更重要的是服務的 響應時間(response time),即客戶端發送請求到接收響應之間的時間。

?

  1. 響應時間:是客戶所看到的,除了實際處理請求的時間( 服務時間(service time) )之外,還包括網絡延遲和排隊延遲;
  2. 延遲:是某個請求等待處理的 持續時長,在此期間它處于 休眠(latent) 狀態,并等待服務。

響應時間的分布

  • 負載不同時:大多數請求是相當快的,但偶爾會出現需要更長的時間的異常值。這也許是因為緩慢的請求實質上開銷更大,例如它們可能會處理更多的數據
  • 負載相同時:即使所有請求都花費相同時間的情況下,隨機的附加延遲也會導致結果變化,例如:1. 上下文切換到后臺進程,2. 網絡數據包丟失與 3. TCP 重傳,4. 垃圾收集暫停,5. 強制從磁盤讀取的頁面錯誤,6. 服務器機架中的震動,還有很多其他原因。

在這里插入圖片描述

圖展示了一個服務 100 次請求響應時間的均值與百分位數

?

3. 應對負載的方法

適應某個級別負載的架構不太可能應付 10 倍于此的負載。如果你正在開發一個快速增長的服務,那么每次負載發生數量級的增長時,你可能都需要重新考慮架構 — 或者更頻繁。

應用系統的問題可能是讀取量、寫入量、要存儲的數據量、數據的復雜度、響應時間要求、訪問模式或者所有問題的大雜燴。

舉個例子,用于處理每秒十萬個請求(每個大小為 1 kB)的系統與用于處理每分鐘 3 個請求(每個大小為 2GB)的系統看上去會非常不一樣,盡管兩個系統有同樣的數據吞吐量

?

一個常用的方法是:

跨多臺機器部署 無狀態服務(stateless services) 非常簡單,但將帶狀態的數據系統從單節點變為分布式配置則可能引入許多額外復雜度(分庫分表、冷熱分離)。出于這個原因,常識告訴我們應該將數據庫放在單個節點上(縱向伸縮),直到伸縮成本或可用性需求迫使其改為分布式

?
根據業務情況來模擬負載情況:

一個良好適配應用的可伸縮架構,是圍繞著 假設(assumption) 建立的:

  • 哪些操作是常見的?哪些操作是罕見的?這就是所謂負載參數。
  • 如果假設最終是錯誤的,那么為伸縮所做的工程投入就白費了,最糟糕的是適得其反。

?

四. 可維護性

眾所周知,軟件的大部分開銷并不在最初的開發階段,而是在持續的維護階段,包括修復漏洞、保持系統正常運行、調查失效、適配新的平臺、為新的場景進行修改、償還技術債和添加新的功能。

我們在設計之初就盡量考慮盡可能減少維護期間的痛苦,從而避免自己的軟件系統變成遺留系統。

為此,我們將特別關注軟件系統的三個設計原則:

  • 可操作性(Operability): 便于運維團隊保持系統平穩運行。
  • 簡單性(Simplicity):從系統中消除盡可能多的 復雜度(complexity),使新工程師也能輕松理解系統。
  • 可演化性(evolvability): 使工程師在未來能輕松地對系統進行更改,當需求變化時為新應用場景做適配。也稱為 可擴展性(extensibility)可修改性(modifiability)可塑性(plasticity)

1. 可操作性:人生苦短,關愛運維

盡管運維的某些方面可以,而且應該是自動化的,但在最初建立正確運作的自動化機制仍然取決于人。

一個優秀運維團隊的典型職責如下(或者更多):

  • 監控系統的運行狀況,并在服務狀態不佳時快速恢復服務。
  • 跟蹤問題的原因,例如系統故障或性能下降。
  • 了解系統間的相互作用,以便在異常變更造成損失前進行規避。
  • 預測未來的問題,并在問題出現之前加以解決(例如,容量規劃)。
  • 建立部署、配置、管理方面的良好實踐,編寫相應工具。
  • 執行復雜的維護任務,例如將應用程序從一個平臺遷移到另一個平臺
  • 定義工作流程,使運維操作可預測,并保持生產環境穩定。
  • 鐵打的營盤流水的兵,維持組織對系統的了解

數據系統可以通過各種方式使日常任務更輕松:

  • 通過良好的監控,提供對系統內部狀態和運行時行為的 可見性(visibility)
  • 為自動化提供良好支持,將系統與標準化工具相集成
  • 避免依賴單臺機器(在整個系統繼續不間斷運行的情況下允許機器停機維護)。
  • 提供良好的文檔和易于理解的操作模型(“如果做 X,會發生 Y”)
  • 提供良好的默認行為,但需要時也允許管理員自由覆蓋默認值。
  • 有條件時進行自我修復(how),但需要時也允許管理員手動控制系統狀態。
  • (系統)行為可預測,最大限度減少意外。

?

2. 簡單性:管理復雜度

復雜度(complexity) 有各種可能的癥狀,例如:狀態空間激增、模塊間緊密耦合、糾結的依賴關系、不一致的命名和術語、解決性能問題的 Hack、需要繞開的特例等等。

降低復雜度能極大提高軟件可維護性

因為復雜度導致維護困難時,預算和時間安排通常會超支。在復雜的軟件中進行變更,引入錯誤的風險也更大:當開發人員難以理解系統時,隱藏的假設、無意的后果和意外的交互就更容易被忽略。 相反,降低復雜度能極大地提高軟件的可維護性,因此簡單性應該是構建系統的一個關鍵目標。

?

通過抽象來降低復雜度

用于消除 額外復雜度 的最好工具之一是 抽象(abstraction)
一個好的抽象可以將大量實現細節隱藏在一個干凈,簡單易懂的外觀下面。比起重復造很多輪子,重用抽象不僅更有效率,而且有助于開發高質量的軟件。抽象組件的質量改進將使所有使用它的應用受益。

?

3. 可演化性:擁抱變化

系統的需求處于常態的變化中,例如:你了解了新的事實、出現意想不到的應用場景、業務優先級發生變化、用戶要求新功能、新平臺取代舊平臺、法律或監管要求發生變化、系統增長迫使架構變化等。

在組織流程方面,敏捷(agile) 工作模式為適應變化提供了一個框架。敏捷社區還開發了對在頻繁變化的環境中開發軟件很有幫助的技術工具和模式,如 測試驅動開發(TDD, test-driven development)重構(refactoring)

?

修改數據系統并使其適應不斷變化需求的容易程度,是與 簡單性抽象性 密切相關的:簡單易懂的系統通常比復雜系統更容易修改。

?

一個應用必須滿足各種需求才稱得上有用。

  • 一些 功能需求(functional requirements,即它應該做什么,比如允許以各種方式存儲,檢索,搜索和處理數據)
  • 一些 非功能性需求(nonfunctional,即通用屬性,例如安全性、可靠性、合規性、可伸縮性、兼容性和可維護性)。在本章詳細討論了可靠性,可伸縮性和可維護性。

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/21308.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/21308.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/21308.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何解決Mac系統創建/home目錄提示Read-Only filesystem(補充)?

繼昨日發布的博文之后,有小伙伴私我說: sudo mount -uw /命令報錯:mount_apfs: volume could not be mounted: Permission denied mount: / failed with 66 今天補充一下昨天的文章,昨天的文章我沒有注明是Mac什么系統的&#x…

Chromebook Plus中添加了Gemini?

Chromebook Plus中添加了Gemini? 前言 就在5月29日,谷歌宣布了一項重大更新,將其Gemini人工智能技術集成到Chromebook Plus筆記本電腦中。這項技術此前已應用于谷歌的其他設備。華碩和惠普已經在市場上銷售的Chromebook Plus機型,…

mysql binlog查看指定數據庫

1.mysql binlog查看指定數據庫的方法 MySQL 的 binlog(二進制日志)主要記錄了數據庫上執行的所有更改數據的 SQL 語句,包括數據的插入、更新和刪除等操作。但直接查看 binlog 并不直觀,因為它是以二進制格式存儲的。為了查看 bin…

電腦缺少dll文件怎么解決,分享幾種靠譜的解決方法

在現代科技高度發達的時代,電腦已經成為我們生活和工作中不可或缺的工具。然而,在使用電腦的過程中,我們可能會遇到一些問題,其中之一就是電腦丟失dll文件。那么,當我們面臨這樣的問題時,應該如何解決呢&am…

云原生架構案例分析_1.某旅行公司云原生改造

隨著云計算的普及與云原生的廣泛應用,越來越多的從業者、決策者清晰地認識到“云原生化將成為企業技術創新的關鍵要素,也是完成企業數字化轉型的最短路徑”。因此,具有前瞻思維的互聯網企業從應用誕生之初就扎根于云端,謹慎穩重的…

BMC壓力測試腳本

說明 對于研發階段而言,需要對BMC執行壓力測試,可以提前發現問題,修復問題,提高產品穩定性。 大體而言,需要做到幾個方面: 1.預先發現是否會造成BMC hang機。2.進程是否會發生重啟,運行異常3.進程是否會…

SpringMVC:轉發和重定向

1. 請求轉發和重定向簡介 參考該鏈接第9點 2. forward 返回下一個資源路徑,請求轉發固定格式:return "forward:資源路徑"如 return "forward:/b" 此時為一次請求返回邏輯視圖名稱 返回邏輯視圖不指定方式時都會默認使用請求轉發in…

【Qt秘籍】[008]-Qt中的connect函數

在Qt框架中,connect函數是一個非常核心的函數,用于實現信號(Signals)和槽(Slots)之間的連接,它是Qt信號槽機制的關鍵所在。信號槽機制是一種高級的通信方式,允許對象在狀態改變時通知…

ChatGPT-3

ChatGPT-3是OpenAI開發的先進人工智能聊天機器人程序,它是基于 GPT-3.5 架構的大型語言模型,并通過強化學習進行了訓練。這項技術代表了自然語言處理領域的一個重要里程碑,具有以下顯著特點和功能: 強大的語言理解和生成能力&…

代碼隨想三刷數組篇

代碼隨想三刷數組篇1 704. 二分查找題目代碼27. 移除元素題目代碼977.有序數組的平方題目代碼209.長度最小的子數組題目代碼59.螺旋矩陣II題目代碼704. 二分查找 題目

牛客網刷題 | BC114 圣誕樹 (不理解)

目前主要分為三個專欄,后續還會添加: 專欄如下: C語言刷題解析 C語言系列文章 我的成長經歷 感謝閱讀! 初來乍到,如有錯誤請指出,感謝! 這道題沒搞懂 也沒找到視…

Nginx源碼編譯安裝

Nginx NginxNginx的特點Nginx的使用場景Nginx 有哪些進程 使用源碼編譯安裝Nginx準備工作安裝依賴包編譯安裝Nginx檢查、啟動、重啟、停止 nginx服務配置 Nginx 系統服務方法一:方法二: 訪問Nginx頁面 升級Nginx準備工作編譯安裝新版本Nginx驗證 Nginx N…

【HarmonyOS】Stage 模型 - UIAbility 的啟動模式

Stage 模型這樣的應用,它在啟動的時候會先準備 Ability Stage 舞臺,接著呢,就可以基于它去創建 UIAbility 的實例,并去啟動它。 UIAbility 組件啟動模式 有四種: singletonstandardmultitonspecified 修改模塊的 mod…

SSMP整合案例第五步 在前端頁面上拿到service層調數據庫里的數據后列表

在前端頁面上列表 我們首先看看前端頁面 我們已經把數據傳入前端控制臺 再看看我們的代碼是怎么寫的 我們展示 數據來自圖dataList 在這里 我們要把數據填進去 就能展示在前端頁面上 用的是前端數據雙向綁定 axios發送異步請求 函數 //鉤子函數,VUE對象初始化…

【四大組件】-- 活動 Activity

目錄 活動活動是什么活動的相關操作手動創建活動活動中使用Toast活動中使用Menu銷毀一個活動 使用Intent實現活動間啟動顯示啟動隱式啟動 活動間數據傳遞活動的生命周期返回棧活動的狀態活動的生存期 活動的啟動流程活動的回收和重建如何在活動銷毀前保存狀態 活動的啟動模式st…

設計模式(十四)行為型模式---訪問者模式(visitor)

文章目錄 訪問者模式簡介分派的分類什么是雙分派?結構UML圖具體實現UML圖代碼實現 優缺點 訪問者模式簡介 訪問者模式(visitor pattern)是封裝一些作用于某種數據結構中的元素的操作,它可以在不改變這個數據結構(實現…

紅隊內網攻防滲透:內網滲透之windows內網權限提升技術:手工篇

紅隊內網攻防滲透 1. 內網權限提升技術1.1 windows內網權限提升技術--手工篇1.1.1 Web到Win-系統提權-人工操作1.1.1.1 信息收集1.1.1.2 補丁篩選1.1.1.3 EXP獲取執行1.1.2 Web到Win-系統提權-土豆家族1.1.2.1 Test in:Windows 10/11(1809/21H2)1.1.2.2 Test in:Windows Se…

全新市場階段,Partisia BlockChain 將向 RWA、DeFi 等領域布局

Partisia Blockchain 是一個全新范式的 Layer1,該鏈通過 MPC 方案來構建鏈上隱私方案,同時該鏈通過系列獨特且創新的設計,旨在進一步解決目前 Web3 中所面臨的不可能三角問題,包括安全性、互操作性和可擴展性,為更多的…

NTFS磁盤格式讀寫工具:Tuxera NTFS 2021 for Mac

Tuxera NTFS 是一款用于 macOS 系統的 NTFS 文件系統驅動程序。NTFS 是 Windows 系統中常用的文件系統,而 macOS 默認只支持讀取 NTFS 格式的磁盤,不能進行寫入操作。因此,如果你需要在 macOS 上進行 NTFS 磁盤的寫入操作,就需要安…

提交一個Bug需要哪些信息?

軟件在使用過程中存在的任何問題都叫做軟件的缺陷,簡稱Bug,我認為要提交一個Bug首先得將這個Bug的核心內容說明一下,比如Bug的核心問題是什么、產生的前提、預期結果是什么、但實際結果是什么、以及附上一個證據圖片。 然后提交時需要Bug報告…