主頁 > 軟體設計 > 訊息佇列為了提高性能使用了哪些細節?

訊息佇列為了提高性能使用了哪些細節?

2020-12-16 10:05:51 軟體設計

1 采用異步設計

假設使用同步實作,偽裝代碼如下:

Transfer(accountFrom, accountTo, amount) {
  // 先從 accountFrom 的賬戶中減去相應的錢數
  Add(accountFrom, -1 * amount)
  // 再把減去的錢數加到 accountTo 的賬戶中
  Add(accountTo, amount)
  return OK
}

  上面的偽代碼首先從 accountFrom 的賬戶中減去相應的錢數,再把減去的錢數加到 accountTo 的賬戶中,這種同步實作是一種很自然方式,簡單直接,那么性能表現如何呢?假設微服務 Add 的平均回應時延是 50ms,那么可以計算出我們實作的微服務 Transfer 的平均回應時延大約等于執行 2 次 Add 的時延,也就是 100ms,那隨著呼叫Transfer 服務的請求越來越多,會出現什么情況呢?

  在這種實作中,每處理一個請求需要耗時 100ms,并在這 100ms 程序中是需要獨占一個執行緒的:每個執行緒每秒鐘最多可以處理 10 個請求,每臺計算機上的執行緒資源并不是無限的,假設我們使用的服務器同時打開的執行緒數量上限是 10,000,可以計算出這臺服務器每秒鐘可以處理的請求上限是: 10,000(個執行緒)* 10(次請求每秒) =100,000 次每秒,如果請求速度超過這個值,那么請求就不能被馬上處理,只能阻塞或者排隊,這時候 Transfer 服務的回應時延由 100ms 延長到了:排隊的等待時延 + 處理時延 (100ms),也就是說,在大量請求的情況下,我們的微服務的平均回應時延變長了,

  這是不是已經到了這臺服務器所能承受的極限了呢?其實遠遠沒有,如果我們監測一下服務器的各項指標,會發現無論是 CPU、記憶體,還是網卡流量或者是磁盤的 IO 都空閑的很,那我們 Transfer 服務中的那 10,000 個執行緒在干什么呢?對,絕大部分執行緒都在等待 Add 服務回傳結果,

采用異步處理

TransferAsync(accountFrom, accountTo, amount, OnComplete()) {
  // 異步從 accountFrom 的賬戶中減去相應的錢數,然后呼叫 OnDebit 方法,
  AddAsync(accountFrom, -1 * amount, OnDebit(accountTo, amount, OnAllDone(OnComplete())))
}
// 扣減賬戶 accountFrom 完成后呼叫
OnDebit(accountTo, amount, OnAllDone(OnComplete())) {
  //  再異步把減去的錢數加到 accountTo 的賬戶中,然后執行 OnAllDone 方法
  AddAsync(accountTo, amount, OnAllDone(OnComplete()))
}
// 轉入賬戶 accountTo 完成后呼叫
OnAllDone(OnComplete()) {
  OnComplete()
}

由于沒有了執行緒的數量的限制,總體吞吐量上限會大大超過同步實作,并且在服務器 CPU、網路帶寬資源達到極限之前,回應時延不會隨著請求數量增加而顯著升高,可以一直保持約 100ms 的平均回應時延,

2 序列化與反序列化資料的壓縮優化

比如我們要序列化一個 User 物件,它包含 3 個屬性,姓名 zhangsan,年齡:23,婚姻狀況:已婚,

User:
  name: "zhangsan"
  age: 23
  married: true

使用 JSON 序列化后:

{"name":"zhangsan","age":"23","married":"true"}

實作高性能的序列化,對于同樣的 User 物件,我們可以把它序列化成這樣:

03   | 08 7a 68 61 6e 67 73 61 6e | 17 | 01
User |    z  h  a  n  g  s  a  n  | 23 | true

03 表示這是一個 User 型別的物件,可以約定按照 name、age、married 這個固定順序來序列化這三個屬性,按照順序,第一個欄位是 name,不存欄位名,直接存欄位值“zhangsan”就可以了,由于名字的長度不固定,用第一個位元組 08 表示這個名字的長度是 8 個位元組,后面的 8 個位元組就是 zhangsan,第二個欄位是年齡,直接用一個位元組表示就可以了,23 的 16 進制是 17 ,最后一個欄位是婚姻狀態,用一個位元組來表示,01 表示已婚,00 表示未婚,這里面保存一個 01,

可以看到,同樣的一個 User 物件,JSON 序列化后需要 47 個位元組,這里只要 12 個位元組就夠了,

3 雙工收發協議

4 使用批量訊息提升服務端處理能力

5 利用 PageCache 加速訊息讀寫

  PageCache 是現代作業系統都具有的一項基本特性,通俗地說,PageCache 就是作業系統在記憶體中給磁盤上的檔案建立的快取,無論我們使用什么語言撰寫的程式,在呼叫系統的 API 讀寫檔案的時候,并不會直接去讀寫磁盤上的檔案,應用程式實際操作的都是 PageCache,也就是檔案在記憶體中快取的副本,應用程式在寫入檔案的時候,作業系統會先把資料寫入到記憶體中的 PageCache,然后再一批一批地寫到磁盤上,讀取檔案的時候,也是從 PageCache 中來讀取資料,這時候會出現兩種可能情況,

  一種是 PageCache 中有資料,那就直接讀取,這樣就節省了從磁盤上讀取資料的時間;另一種情況是,PageCache 中沒有資料,這時候作業系統會引發一個缺頁中斷,應用程式的讀取執行緒會被阻塞,作業系統把資料從檔案中復制到 PageCache 中,然后應用程式再從 PageCache 中繼續把資料讀出來,這時會真正讀一次磁盤上的檔案,這個讀的程序就會比較慢,用戶的應用程式在使用完某塊 PageCache 后,作業系統并不會立刻就清除這個 PageCache,而是盡可能地利用空閑的物理記憶體保存這些 PageCache,除非系統記憶體不夠用,作業系統才會清理掉一部分 PageCache,清理的策略一般是 LRU 或它的變種演算法,這個演算法我們不展開講,它保留 PageCache 的邏輯是:優先保留最近一段時間最常使用的那些 PageCache,

  例如Kafka 在讀寫訊息檔案的時候,充分利用了 PageCache 的特性,一般來說,訊息剛剛寫入到服務端就會被消費,按照 LRU 的“優先清除最近最少使用的頁”這種策略,讀取的時候,對于這種剛剛寫入的 PageCache,命中的幾率會非常高,也就是說,大部分情況下,消費讀訊息都會命中 PageCache,帶來的好處有兩個:一個是讀取的速度會非常快,另外一個是,給寫入訊息讓出磁盤的 IO 資源,間接也提升了寫入的性能, 

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/235385.html

標籤:其他

上一篇:訊息佇列為了提高性能使用了哪些細節?

下一篇:Linux 網站服務動態站點 創建論壇服務 決議

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more