讀構建可擴展分散式系統:方法與實踐15可擴展系統的基本要素

来源:https://www.cnblogs.com/lying7/p/18431055
-Advertisement-
Play Games

1. 可擴展系統的基本要素 1.1. 分散式系統在本質上就是複雜的,你必須考慮多種故障模式,並設計應對所有可能發生的情況的處理方式 1.2. 大規模應用程式需要協調大量的硬體和軟體組件,共同實現低延遲和高吞吐量的能力 1.3. 面臨的挑戰是將所有活動部件組合成一個應用程式來運行,使其既能滿足需求又不 ...


1. 可擴展系統的基本要素

1.1. 分散式系統在本質上就是複雜的,你必須考慮多種故障模式,並設計應對所有可能發生的情況的處理方式

1.2. 大規模應用程式需要協調大量的硬體和軟體組件,共同實現低延遲和高吞吐量的能力

1.3. 面臨的挑戰是將所有活動部件組合成一個應用程式來運行,使其既能滿足需求又不會耗費過多成本

  • 1.3.1. 新的編程抽象、平臺模型和硬體讓你更容易構建具有更高的性能、更好的可擴展性和更大的彈性的更複雜的系統

2. 自動化

2.1. 在構建大型系統時,工程師是相當昂貴但必不可少的資源

2.2. 需要部署頻繁的更改來改善客戶體驗,並確保可靠和可擴展的操作

2.3. 在不停機的情況下每天有效地將數百個更改推送到已部署系統的能力是系統規模化的關鍵所在

2.4. 促進自動化的一組工具和實踐體現在DevOps文化中

  • 2.4.1. DevOps包含一組面向從開發到部署各個級別過程的自動化實踐和工具

  • 2.4.2. DevOps的核心是持續交付(CD)實踐,由用於代碼配置管理、自動化測試、部署和監控的複雜工具鏈提供支持

2.5. DevOps實踐對於成功的可擴展系統至關重要

  • 2.5.1. 團隊有責任設計、開發和運營他們的微服務,微服務通過良好定義的介面與系統的其餘部分進行交互

  • 2.5.2. 藉助自動化工具鏈,可以在微服務中獨立部署本地更改和新功能,同時不幹擾系統操作

  • 2.5.3. 自動化減少了協調開銷,提高了生產力,縮短了發佈周期

  • 2.5.4. 意味著你的工程投資將獲得更大的回報

3. 可觀測性

3.1. 你無法管理你無法衡量的東西

3.2. 由於有大量移動部件,所有部件都在可變負載條件下運行,容易出現不可預測的錯誤

3.3. 需要藉助測量系統提供的健康狀況和行為來觀測系統狀態

  • 3.3.1. 提供基礎設施不斷生成的細粒度指標和日誌數據來捕獲系統當前狀態

  • 3.3.2. 分析聚合實時指標並採取行動,對指示實際或未決故障的警報做出反應

3.4. 可觀測性的第一個基本要素是具有一個儀錶化系統,它不斷以指標和日誌條目的形式發出系統遙測數據

  • 3.4.1. 可以來自操作系統、你在應用程式中使用的基礎平臺(例如,消息傳遞、資料庫)以及你部署的應用程式代碼

  • 3.4.2. 指標表示資源利用率以及系統各部分提供的延遲、響應時間和吞吐量

3.5. 代碼檢測是強制性的,你可以使用開源框架或專有解決方案

  • 3.5.1. 指標和日誌條目形成了基於時間序列的連續的數據流,表徵了你的應用程式隨時間的行為

3.6. 捕獲原始指標數據是可觀測性系統推斷並感知態勢的先決條件

  • 3.6.1. 需要快速處理數據流,它才可能讓系統及時採取行動

  • 3.6.2. 包括持續監控當前狀態、探索歷史數據以瞭解或診斷一些意外的系統行為,以及在超過閾值或發生故障時發送實時警報

3.7. Prometheus、Grafana和Graphite是目前廣泛使用的技術,它們提供了適用於可觀測性棧各個部分的開箱即用的解決方案

3.8. 可觀測性是可擴展分散式系統的必要組成部分

4. 部署平臺

4.1. 可擴展系統需要大規模、有彈性且可靠的計算和數據平臺

4.2. 可以使用專為操作設計的腳本語言自動調用配置

  • 4.2.1. 基礎架構即代碼(IaC),也是DevOps的基本要素

4.3. 傳統上,虛擬機是應用程式的部署單元

  • 4.3.1. 容器鏡像支持將應用程式代碼和依賴項打包到單個可部署單元中

  • 4.3.2. 與虛擬機相比,容器消耗的資源更少,因此可以在單個虛擬機上打包多個容器,更有效地利用硬體資源

4.4. 容器通常與集群管理平臺(如Kubernetes或Apache Mesos)一起使用

  • 4.4.1. 容器編排平臺為你提供API來控制容器的執行方式、時間和位置

  • 4.4.2. 平臺允許你自動部署容器並支持使用自動縮放的不同系統負載,簡化集群中在多個節點部署多個容器的管理工作

5. 數據湖

5.1. 隨著時間的推移,你的系統將生成許多PB級或更多的數據

  • 5.1.1. 數據中的大部分很少被你的用戶訪問

5.2. 管理、組織和存儲歷史數據存儲庫是數據倉庫、大數據和數據湖的領域範圍所在

  • 5.2.1. 本質是以一種可以檢索、查詢和分析的形式來存儲歷史數據

5.3. 數據湖的特征是以異構格式存儲和編目數據,從原生blob到JSON再到關係資料庫提取數據

  • 5.3.1. 利用Apache Hadoop、Amazon S3或Microsoft Azure Data Lake等低成本對象存儲

  • 5.3.2. 靈活的查詢引擎支持數據的分析和轉換

  • 5.3.3. 可以使用不同的存儲類別,以本質上更長的檢索時間換取更低的成本,繼而優化成本

6. 併發系統

6.1. 分散式系統包括多個獨立的代碼片段,它們在不同位置的多個處理節點上並行或併發地執行

6.2. 任何分散式系統都是併發系統,即使每個節點一次只處理一個事件也是如此

  • 6.2.1. 在分散式系統中協調節點充滿了風險

6.3. 編寫軟體來併發地執行多個操作,有助於優化單個節點上的處理能力和資源利用率,提高本地和系統範圍的處理能力

6.4. 在過去的計算時代,每個CPU在任何時刻都只能執行一條機器指令

  • 6.4.1. 程式試圖讀取文件或在網路上發送消息時,它必須與CPU外圍的硬體子系統(磁碟、網卡)進行交互

  • 6.4.2. 從硬碟讀取數據大約需要10ms。在此期間,程式必須等待可供處理的數據

  • 6.4.3. Linux等操作系統可以在單個CPU上運行多個程式的方式

  • 6.4.4. 將軟體明確地構造成具有多個可以並行執行的活動,在其他任務等待I/O時,操作系統可以安排有工作要做的任務

6.5. 使用多核晶元,可以在每個內核上併發執行具有多個並行活動的軟體系統,最多可達到可用內核的數量

  • 6.5.1. 每種編程語言都有自己的線程機制

  • 6.5.2. 所有併發機制的底層語義都是相似的

  • 6.5.3. 主流使用的主要線程模型只有幾個

6.6. 在過去50年裡,併發模型一直是電腦科學中研究和探索較多的主題

  • 6.6.1. CSP(通信順序進程)模型構成了Go併發特性的基礎

  • 6.6.1.1. 在Go中,併發的單位是goroutine,goroutine使用無緩衝或緩衝通道發送消息來進行通信

  • 6.6.2. Erlang實現了併發的actor模型

  • 6.6.2.1. actor是沒有共用狀態的輕量級進程,通過向其他actor發送非同步消息來進行通信

  • 6.6.2.2. actor使用郵箱或隊列來緩衝消息,可以使用模式匹配來選擇要處理的消息

  • 6.6.3. Node.js避開多線程,利用由事件迴圈管理的單線程非阻塞模型

  • 6.6.3.1. 該模型適用於頻繁執行I/O請求的代碼

  • 6.6.3.2. 如果你的代碼需要執行CPU密集型操作,例如對大型列表進行排序,那麼你只有一個線程

>  6.6.3.2.1. 這將阻止其他請求,直到排序完成

>  6.6.3.2.2. 這並非一種理想的情況

6.7. 在可擴展分散式系統的世界中,併發是無處不在的

6.8. 無論你使用的是C/C++中的pthreads庫,還是受CSP啟發的經典Go併發模型,需要避免的問題都是相同的

7. 線程

7.1. 預設情況下,每個軟體進程都有一個執行線程,即操作系統在安排進程執行時所管理的線程

7.2. 線程本質上是我們構建可擴展分散式系統時用於數據處理和資料庫平臺的組件

7.3. 在許多情況下,你可能不會顯式編寫多線程代碼

7.4. 許多平臺還通過配置參數來調整其併發能力,這意味著要調整系統性能,你需要瞭解更改各種線程和線程池設置的影響

7.5. 線程執行順序

  • 7.5.1. 從程式開發者的角度來看,執行順序是不確定的(nondeterministic)

  • 7.5.2. 不確定性(nondeterminism)這個概念是理解多線程代碼的基礎

  • 7.5.3. 一旦調度程式允許一個線程在CPU上執行一段時間,它就可以在指定的時間段後中斷該線程,並安排另一個線程運行

  • 7.5.3.1. 中斷稱為搶占

  • 7.5.4. 調度程式根據調度演算法決定何時運行哪個線程,線程是獨立且非同步地運行,直到完成

  • 7.5.5. 無論線程執行的順序如何(你無法控制)​,你的代碼都應該產生正確的結果

7.6. 線程的狀態

  • 7.6.1. 多線程系統有一個系統調度程式來決定何時運行哪些線程

  • 7.6.1.1. 執行最高優先順序的線程

7.7. 線程池

  • 7.7.1. 許多多線程系統需要創建和管理一組執行相似任務的線程

  • 7.7.2. 線程集合為線程池

  • 7.7.2.1. 線程池包含多個工作線程,它們通常執行相似的任務,並以一個集合進行管理

  • 7.7.3. 如果系統以不受約束的方式創建線程,最終會耗盡記憶體,導致系統崩潰

7.8. 同步屏障

  • 7.8.1. CountDownLatch是一個簡單的同步屏障器

  • 7.8.1.1. 它是一次性工具,初始化值無法重置

8. 線程引入的問題

8.1. 併發編程的基本問題是如何協調多個線程的執行,無論它們以何種順序執行,都會產生正確的結果

8.2. 鑒於線程可以不確定地被啟動和搶占,任何中等複雜的程式本質上都有無數種執行順序

  • 8.2.1. 這些系統是不容易測試的

8.3. 所有併發程式都需要避免兩個基本問題,即競態條件和死鎖

8.4. 競態條件

  • 8.4.1. 如果每個線程都只做自己的事情並且完全獨立,執行順序就不是問題了

  • 8.4.2. 完全獨立的線程並不是大多數多線程系統的行為方式

  • 8.4.3. 線程可以使用共用的數據結構來協調它們的工作併在線程之間傳遞狀態

  • 8.4.4. 競態條件是隱秘的、狡猾的錯誤,因為它們通常很少見,而且很難被髮現,大多數時候結果都是正確的

  • 8.4.4.1. 相同的代碼,偶爾會出現不同的結果

  • 8.4.4.2. 關鍵是識別和保護臨界區

  • 8.4.4.3. 臨界區是更新共用數據結構的一段代碼,如果它被多個線程訪問,則必須以原子方式執行

  • 8.4.4.4. 你應該使臨界區代碼儘可能少,將序列化代碼減到最少

8.5. 死鎖

  • 8.5.1. 如果我們不小心編寫過多限制不確定性的代碼,則又會導致程式停止運行,並且永遠不會繼續執行,術語稱其為死鎖

  • 8.5.2. 當兩個或多個線程永遠被阻塞,沒有一個可以繼續執行時,就會發生死鎖

  • 8.5.2.1. 當線程需要獨占共用資源集,以不同的順序獲取鎖時,就會發生這種情況

  • 8.5.3. 死鎖,也稱為致命擁抱,會導致程式停止

  • 8.5.4. 可以在軟體的阻塞操作上使用超時來實現

  • 8.5.4.1. 在超時到期後,一個線程釋放臨界區並重試,讓其他被阻塞的線程有機會繼續執行

  • 8.5.4.2. 阻塞線程會損害性能,設置超時值也不是精確的做法

  • 8.5.5. 對於迴圈等待死鎖,可以在共用資源上施加資源分配協議來解決,這樣線程就不會總是以相同的順序請求資源了

9. 線程間的協調

9.1. 很多時候,我們需要不同角色的線程來協調它們的活動,繼而解決問題

9.2. 列印問題就是典型的生產者-消費者的例子

  • 9.2.1. 與一切現實的資源一樣,緩衝區的容量也是有限的

  • 9.2.2. 輪詢,或忙等待

  • 9.2.3. 更好的解決方案是讓生產者和消費者阻塞,直到其期望的操作(分別為put或get)成功

  • 9.2.4. 阻塞的線程不消耗資源,這是一個有效的解決方案

10. 線程安全集合

10.1. java.util包中的集合併不是線程安全的

  • 10.1.1. 為了加快單線程程式的執行速度,該集合不是線程安全的

10.2. 在多線程代碼中使用線程安全集合總是更安全

  • 10.2.1. ConcurrentHashMap的迭代器是弱一致性

  • 10.2.2. 如果你需要一個在被多個線程更新時始終反映當前hashmap狀態的迭代器,就要付出性能代價,ConcurrentHashMap不是正確的選擇


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • title: 深入理解 Nuxt 中的 app created 鉤子 date: 2024/9/26 updated: 2024/9/26 author: cmdragon excerpt: 摘要:本文深入介紹了 Nuxt.js 中的 app:created 鉤子,包括其觸發時機、用途及使用方法。通 ...
  • 一、流水管線 實現邏輯: 1)先自定義幾個點,通過CatmullRomCurve3生成一條平滑曲線 2)根據生成的曲線在XY面擴展一個面,其中需要註意頂點索引、UV坐標添加的順序,否則可能會導致繪製的圖片混亂,不是完整的圖片 3)添加紋理同時設置偏移量實現流動效果 4)為了保證顯示的箭頭圖標不失真, ...
  • title: Nuxt Kit 實用工具的使用示例 date: 2024/9/25 updated: 2024/9/25 author: cmdragon excerpt: 摘要:本文介紹了Nuxt Kit工具在開發集成工具或插件時,如何訪問和修改Nuxt應用中使用的Vite或webpack配置,以 ...
  • 混淆指定js文件 fomartJs.bat @echo off REM 定義一個包含文件名的數組 set jsFiles=("polyfills.b4665eab.js" "manifest.b09f6bad.js" "index.f8bec5fb.js") REM 遍曆數組中的每個文件 for % ...
  • title: 使用 Nuxt Kit 的構建器 API 來擴展配置 date: 2024/9/24 updated: 2024/9/24 author: cmdragon excerpt: 摘要:本文詳細介紹瞭如何使用 Nuxt Kit 的構建器 API 來擴展和定製 Nuxt 3 項目的 webp ...
  • 前言 React在很早之前的版本中加了useId,用於生成唯一ID。在Vue3.5版本中,終於也有了期待已久的useId。這篇文章來帶你搞清楚useId有哪些應用場景,以及他是如何實現的。 關註公眾號:【前端歐陽】,給自己一個進階vue的機會 useId的作用 他的作用也是生成唯一ID,同一個Vue ...
  • 1. 基本信息 構建可擴展分散式系統:方法與實踐 [美]伊恩·戈頓(Ian Gorton)著 機械工業出版社,2024年5月出版 1.1. 讀薄率 書籍總字數188千字,筆記總字數49688字。 讀薄率49688÷188000≈26.4% 1.2. 讀厚方向 設計模式:可復用面向對象軟體的基礎 程式 ...
  • 軟體工程課程 班級鏈接 作業要求 作業鏈接 作業目標 需求分析和原型設計 學號 102201312 隊友 102201311張碩 使用墨刀構建原型,原型鏈接:請點擊我 客戶現實困擾 ​ 在大學里,一些有想法的學生希望通過發起或參與跨專業的項目(創業、學術)來提升自己的綜合能力,拓寬知識面和積累人脈。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...