<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Discord技術(shù)架構(gòu)調(diào)研(IM即時通訊技術(shù)架構(gòu)分析)

       

      一、目標

      • 調(diào)研 discord 的整體架構(gòu),發(fā)掘可為所用的設(shè)計思想

      二、調(diào)研背景

      • Discord作為目前比較火的一個在線聊天和語音通信平臺且具有豐富的功能。另外其 “超級”群 概念號稱可支持百萬級群聊 以及 永久保留用戶聊天記錄。探究其相關(guān)技術(shù)架構(gòu)與技術(shù)實現(xiàn)

      三、產(chǎn)品介紹

      • 目前廣泛使用的在線聊天和語音通信平臺。最初于2015年發(fā)布,旨在為游戲社區(qū)提供一個交流和協(xié)作的平臺,但現(xiàn)在已經(jīng)擴展到各種不同的領(lǐng)域。

      3.1、主要功能

      1. 文字聊天:用戶可以在頻道中發(fā)送消息,與其他成員進行實時交流。這些消息可以包含文字、表情符號、圖片、鏈接等。
      2. 語音通話:用戶可以通過Discord內(nèi)置的語音通話功能與其他成員進行語音交流。這對于組織游戲團隊、進行遠程會議或與朋友進行語音聊天非常有用。
      3. 視頻通話:除了語音通話,Discord還提供了視頻通話功能,使用戶可以進行面對面的視頻交流。
      4. 服務(wù)器和頻道:用戶可以創(chuàng)建自己的服務(wù)器,并在服務(wù)器內(nèi)創(chuàng)建不同的頻道,以便根據(jù)主題或目的進行組織和交流。
      5. 社交功能:Discord具有添加好友、私信、創(chuàng)建群組等社交功能,讓用戶可以與其他用戶建立聯(lián)系和交流。
      6. 權(quán)限和角色管理:服務(wù)器所有者可以設(shè)置不同的權(quán)限和角色,以控制成員對頻道和服務(wù)器的訪問和操作權(quán)限。
      7. 集成和插件:Discord可以與其他應(yīng)用程序和服務(wù)進行集成,例如Twitch、YouTube、Spotify等,以便在聊天中共享內(nèi)容或接收通知。
      8. Bots(機器人):用戶可以添加各種機器人來執(zhí)行各種任務(wù),例如管理服務(wù)器、播放音樂、提供實用工具等。

      3.2、發(fā)展歷程

       

      3.3、數(shù)據(jù)情況

      3.3.1、用戶及群數(shù)據(jù)

      • 總用戶數(shù)未知,預(yù)計1.5 億月活躍用戶,平臺上有 1900 萬個服務(wù)器,涵蓋游戲、投資、政治、動漫等領(lǐng)域。2020 年,Discord 每周有 670 萬服務(wù)器處于活躍狀態(tài),基本上每周都有某個給定話題的對話討論。2021 年,Discord 每周活躍服務(wù)器數(shù)據(jù)增長到了 1900 萬。

      3.3.2、活躍數(shù)據(jù)

      • Discord 平臺上單個日活躍用戶(DAU)與平臺的平均互動時長,是游戲直播平臺 Twitch 的兩倍,同時還是 Facebook Gaming、TikTok、Reddit 以及 Snap 等頭部社交平臺的兩倍以上。

      3.3.3、收入情況

      • 較少的商業(yè)化的動作,Discord 的每用戶平均收入 (ARPU) 僅為 1.30 美元,在公共社交媒體公司中排名非常靠后。

      四、調(diào)研方向

      1. 整體技術(shù)架構(gòu)
      2. 外部集成&開放能力
      3. 技術(shù)棧應(yīng)用情況
      4. 核心業(yè)務(wù)模塊設(shè)計
      5. 核心基礎(chǔ)組件設(shè)計與基礎(chǔ)建設(shè)

      五、調(diào)研內(nèi)容來源

      • 因discord是一個商業(yè)產(chǎn)品且并未開源,國內(nèi)相關(guān)資料也較少。所以只能通過閱讀官方博客與開發(fā)者平臺進行分析、推導(dǎo)與猜想
      • 官方博客:https://discord.com/blog
      • 開發(fā)者平臺:https://discord.com/developers/docs/reference

      六、調(diào)研內(nèi)容

      6.1、 整體架構(gòu)

       

      discord開發(fā)團隊核心理念
      1. 擁抱開源的同時,對開源中間件做自己的特定優(yōu)化與增強
      2. 隨時保持基建可替換
      3. 盡可能降低架構(gòu)與業(yè)務(wù)開發(fā)復(fù)雜度

      6.2、 外部集成&開放能力

      6.2.1、open api

      • 開放接口,其中主要包括 公會相關(guān)操作、表情符號、webhook等開放能力
      6.2.1.1、公會相關(guān)操作
      • 在Discord 中的公會(一般也叫“服務(wù)器”)代表用戶和頻道的集合
        • 一個公會下可以有多個頻道,每個頻道消息隔離,成員共享
      • 提供了公會增刪改查、語音狀態(tài)等管理接口
      6.2.1.2、表情符號
      • 支持開發(fā)者可自定義表情包與符號。并提供其管理能力
      6.2.1.3、webhook
      • Webhooks 是一種不需要用戶主動發(fā)起或者機器人交互在 Discord 中向頻道發(fā)布消息的方式
      • 主要用于系統(tǒng)消息的主動發(fā)送

      6.2.2、gateway

      • 允許開發(fā)者通過WebSocket對關(guān)鍵事件進行訂閱與監(jiān)聽,最終推送給開發(fā)者
      • 可以接收有關(guān)服務(wù)器/公會中發(fā)生的操作事件,例如更新頻道或創(chuàng)建角色。在某些情況下,應(yīng)用還會使用網(wǎng)關(guān)連接來更新或請求資源,例如更新語音狀態(tài)時。

      6.2.3、機器人

      • Discord 提供了機器人用戶能力,這是一種自動化的用戶類型(每個類型的機器人背后都有一個運行程序,可通過sdk方式進行集成)
        • 類似于微信公眾號的機器人功能
      • 用戶可通過斜杠“/”命令與機器人進行交互。

      6.2.4、GameSDK

      • 通過提供GameSDK讓游戲開發(fā)者進行集成,來幫助游戲開發(fā)與discord進行交互
      • 如:游戲狀態(tài)管理、網(wǎng)絡(luò)組件、用戶關(guān)系、邀請等相關(guān)交互功能

      6.2.5、RPC(內(nèi)測中)

      • Discord 客戶端會提供一個在本地主機上運行的 RPC 服務(wù)器,允許開發(fā)者在客戶端來控制本地 Discord
      • 通過本地調(diào)用無服務(wù)器方式讓游戲開發(fā)的客戶端可直接與本地discord客戶端進行交互
        • 如:rtc控制、公會/頻道 管理等

      6.3、 技術(shù)棧說明

      6.3.1、客戶端

      • 提供移動端與桌面端兩種 客戶端形式供用戶使用
      • 移動端使用react native進行跨端業(yè)務(wù)實現(xiàn)
      • 桌面端使用electron進行的web套殼實現(xiàn)
      • 底層組件使用rust進行開發(fā)

      6.3.2、服務(wù)端

      6.3.2.1、語言相關(guān)

      • 多種主流語言進行混合開發(fā)
      • 短鏈api使用python進行快速迭代
      • 長鏈gateway使用erlang的變種語言Elixir進行開發(fā)
      • 核心業(yè)務(wù)早期使用Elixir與golang兩種語言進行開發(fā)
        • 其中g(shù)olang主要實現(xiàn)rtc與音頻相關(guān)業(yè)務(wù)服務(wù)
        • Elixir主要實現(xiàn)im、工會等核心業(yè)務(wù)相關(guān)服務(wù)
          • 其中一些性能優(yōu)化,組件迭代使用rust增強實現(xiàn),Elixir通過NIF方式進行調(diào)用
      • 經(jīng)過長久迭代,discord開發(fā)團隊認為golang gc問題是個詬病,正在逐步進行遷移至rust語言
      • 底層組件服務(wù)使用rust實現(xiàn),以達到高性能服務(wù)提供
      • 內(nèi)部服務(wù)使用grpc進行通信

      6.3.2.2、應(yīng)用系統(tǒng)架構(gòu)

      • 整體通過響應(yīng)式架構(gòu)進行設(shè)計開發(fā)
      • 響應(yīng)式架構(gòu)特點:
        • “流”式編程 (連續(xù)、異步、可觀察)
        • 有效地處理并發(fā)請求,提高系統(tǒng)的吞吐量
        • 消息/事件驅(qū)動,有助于系統(tǒng)的解耦,提高系統(tǒng)的擴展性和彈性。

      6.3.2.3、基建相關(guān)

      • ETCD:
        • grpc注冊中心與服務(wù)發(fā)現(xiàn)
        • 組件集群注冊管理(如消息檢索es管理,后面會詳細說)
      • redis: es負載信息存儲與緩存
      • 數(shù)據(jù)存儲
        • Mongo -> Cassandra -> ScyllaDB (存在演進過程,后面會詳細說

      6.4、核心業(yè)務(wù)模塊

      6.4.1、消息模塊

      • discord消息相關(guān)有兩個比較關(guān)鍵的點,一個是支持非常靈活的消息樣式,另外一個就是其“超級”群消息是如何扇出的

      6.4.1.1、 消息組件(協(xié)議)

      關(guān)鍵協(xié)議摘取
      字段名
      類型
      作用
      描述
      mention_everyone
      bool
      是否提及所有人
      at所有人
      mentions
      user數(shù)組
      提及到的人
      at的所有人
      attachments
      消息附件實體數(shù)組
      附件
      主要描述消息內(nèi)攜帶的文件內(nèi)容
      pinned
      bool
      是否置頂
      消息置頂
      message_reference
      消息實體
      引用的消息
      被引用的歷史消息
      embeds
      消息嵌入實體數(shù)組
      嵌入信息
      主要描述消息內(nèi)嵌入的圖片、視頻等內(nèi)容
      type
      integer
      消息類型
       
      消息的類型,詳情可看下文。
      https://discord.com/developers/docs/resources/channel#message-object-message-types
      content
      string
      消息內(nèi)容
      消息內(nèi)容
      components
      消息組件實體數(shù)組
      組件
      消息內(nèi)嵌入的既定組件。下面會想說
      • 其中components代表的是消息的定義擴展(消息組件),如消息卡片、選擇按鈕等都是基于此實現(xiàn)。其余字段均為關(guān)鍵業(yè)務(wù)字段。
      • 此處只摘取了關(guān)鍵字段,次要未進行摘取。如有興趣可祥看:https://discord.com/developers/docs/resources/channel#message-object
      消息組件
      • 消息組件主要由組件類型與嵌入組件兩個屬性,具體的組件內(nèi)容不同組件類型均不一樣。
        • 組件可以嵌入組件。如多選下拉菜單
      eg:
      
      
      {
          "content": "This is a message with components",
          "components": [
              {
                  "type": 1,
                  "components": []
              }
          ]
      }
      
      

       

       
      目前支持的組件類型
      • 下面會對主要組件類型進行單一分析,因為其components字段是個數(shù)組所以實際應(yīng)用場景可進行組裝
      • 下文會對主要類型進行分析,其他組件可祥見:https://discord.com/developers/docs/interactions/message-components
      組件交互
      • 組件分為交互與非交互組件
      • 其中交互組件會與開發(fā)者服務(wù)進行交互,交互形式有兩種方式可選
        • 上面提到的gateway進行監(jiān)聽與回復(fù)
        • 上面提到的open api中的webhook進行接收與返回
      Action Row (嵌入組件)
      • 是其他類型組件的非action row組件的容器。
        • 每條消息最多可以有 5 個Action Row
        • 一個Action Row不能包含另一個Action Row
      Button (按鈕組件)
      組件協(xié)議
      說明
      按鈕有多種樣式來傳達不同類型的操作。這些樣式還定義哪些字段對按鈕有效。
      • 非鏈接按鈕必須custom_id,并且不能有url
      • 鏈接按鈕必須url,并且不能有custom_id
      • 鏈接按鈕在點擊時不會向開發(fā)者的服務(wù)發(fā)起交互,僅會做鏈接跳轉(zhuǎn)
      按鈕可選樣式
      eg
      
      
      {
          "content": "This is a message with components",
          "components": [
              {
                  "type": 1,
                  "components": [
                      {
                          "type": 2,
                          "label": "Click me!",
                          "style": 1,
                          "custom_id": "click_one"
                      }
                  ]
      
              }
          ]
      }
      
      

       

       
      Select Menus(多選下拉菜單)
      組件協(xié)議
      說明
      • 比較關(guān)鍵的就是options該屬性是多選下拉菜單的關(guān)鍵參數(shù),該參數(shù)定義了每個選項的具體內(nèi)容
      option結(jié)構(gòu)
      eg:
      // This is a message
      {
          "content": "Mason is looking for new arena partners. What classes do you play?",
          "components": [
              {
                  "type": 1,
                  "components": [
                      {
                          "type": 3,
                          "custom_id": "class_select_1",
                          "options":[
                              {
                                  "label": "Rogue",
                                  "value": "rogue",
                                  "description": "Sneak n stab",
                                  "emoji": {
                                      "name": "rogue",
                                      "id": "625891304148303894"
                                  }
                              },
                              {
                                  "label": "Mage",
                                  "value": "mage",
                                  "description": "Turn 'em into a sheep",
                                  "emoji": {
                                      "name": "mage",
                                      "id": "625891304081063986"
                                  }
                              },
                              {
                                  "label": "Priest",
                                  "value": "priest",
                                  "description": "You get heals when I'm done doing damage",
                                  "emoji": {
                                      "name": "priest",
                                      "id": "625891303795982337"
                                  }
                              }
                          ],
                          "placeholder": "Choose a class",
                          "min_values": 1,
                          "max_values": 3
                      }
                  ]
              }
          ]
      }

       

       

      6.4.1.2、 消息扇出流程

      整體架構(gòu)
      說明
      • 一條消息從發(fā)出到扇出的流程是:api服務(wù)將消息發(fā)送到工會服務(wù)(有狀態(tài)節(jié)點,與公會進行綁定),工會服務(wù)將消息均勻發(fā)到中繼節(jié)點。中繼節(jié)點將消息發(fā)送給session網(wǎng)關(guān)。最終推送到用戶手機
      • 其中公會服務(wù)負責消息權(quán)限等基礎(chǔ)功能校驗(也就是校驗該消息是否允許被發(fā)出)
      • 公會服務(wù)校驗完畢,將消息均勻分布到中繼節(jié)點,由特定中繼節(jié)點來處理具體的扇出流程
      • 其中扇出目標用戶僅為在線用戶,所以在用戶登錄后,discord相關(guān)服務(wù)會更新相關(guān)用戶所有服務(wù)器的在線列表,此時中繼服務(wù)僅需對在線成員進行扇出即可
      • 中繼節(jié)點獲取到在線成員后,會校驗該用戶是否有權(quán)限進行接收,最終對可接受用戶將消息發(fā)送給session網(wǎng)關(guān)。最終推送到用戶手機
      ETS(項式存儲)
      • 因為部分公會在線成員可能較多,遠程獲取也會有較大的損耗,discord在初期會在中繼服務(wù)中緩存每個相關(guān)公會的成員信息,但這是恐怖的,在發(fā)展后期,達到了百萬計的成員。機器內(nèi)存成本極高,discord開發(fā)團隊對該部分進行了優(yōu)化
      • 其中主要是將中繼服務(wù)內(nèi)緩存的公會成員信息優(yōu)化打到erlang 的ETS中進行存儲緩存(Erlang虛擬機級別共享內(nèi)存)
      • 并啟動worker進行對ETS 中的數(shù)據(jù)進行統(tǒng)一管理(inserts, updates, deletes)

       

       

      6.4.2、推送模塊(genstage)

      背景
      • discord為應(yīng)對突發(fā)通知過載問題,設(shè)計了genstage模塊用于消息推送
      • 當時主要瓶頸在于向谷歌的 Firebase 云消息服務(wù)發(fā)送推送通知。
        • Firebase 要求每個 XMPP 連接每次待處理的請求不得超過 100 個。如果有 100 個請求正在處理中,就必須等 Firebase 確認一個請求后再發(fā)送另一個請求。
        • 由于一次只能有 100 個請求待處理,因此需要設(shè)計新系統(tǒng),使 XMPP 連接在突發(fā)情況下不會過載。
      整體架構(gòu)
      說明
      • 將系統(tǒng)分為兩個 GenStage 階段。一個source,一個sink
        • 階段1 - source(推送收集器)
          • 是收集推送請求的生產(chǎn)者。每臺機器都會有一個推送收集器 Erlang 進程。
        • 階段2 - sink(推送者)
          • 是一個消費者,它從推送收集器獲取推送請求,并將請求推送到 Firebase。它一次只需要 100 個請求,以確保不會超過 Firebase 的待處理請求限制。每臺機器上有多個 Erlang 進程。
      • GenStage 還有有兩個關(guān)鍵功能可在突發(fā)情況下提供幫助:背壓與甩負荷。
        • 背壓:
          • source會詢問sink所能處理的最大請求數(shù)。這就確保了sink待處理的推送請求數(shù)量的上限。當 Firebase 確認請求時,sink會向source提出更多請求(sink知道 Firebase XMPP 連接所能處理的確切數(shù)量)。
          • 除非sink提出請求,否則source絕不會向sink發(fā)送請求。這就保證了sink永遠都是無壓力的
        • 甩負荷:
          • 由于 sink會對source產(chǎn)生反向壓力,source就會有一個潛在的瓶頸。超大規(guī)模的突發(fā)可能會使source超載。
          • 所以source 還會有一個內(nèi)置功能可以處理這個問題:緩沖事件
            • 在source中,可以指定緩沖多少個推送請求。一般情況下,緩沖區(qū)是空的,但在突發(fā)通知的情況下,緩沖區(qū)就會派上用場。用于緩沖sink無法處理的事件
          • 如果系統(tǒng)中的消息太多,也就是緩沖區(qū)達到瓶頸,source就會停止接收推送請求(丟棄或降級)
            • 思考:此處可以基于業(yè)務(wù)策略進行降級,如部分不重要推送進行直接丟棄,重要推送進行降級緩沖
      效果指標
      Sink推送數(shù)量/分鐘
      Source 緩沖事件數(shù)量/分鐘

      6.5、核心基礎(chǔ)組件與基礎(chǔ)建設(shè)

      6.5.1、存儲演進過程與 服務(wù)架構(gòu)流程

      6.5.1.1、 存儲db演進過程

       

      早期:mongo單分片
      • 單副本集的 MongoDB,沒有使用 MongoDB 的分片,他們給出的理由是當時 MongoDB 分片很難用,而且不夠穩(wěn)定(這里就不去深究了)。消息數(shù)到達一億條時,RAM 里已經(jīng)存不下這么多數(shù)據(jù)和索引,MongoDB 的延時開始變得不可控。
      中期:從 MongoDB 到 Cassandra
      業(yè)務(wù)背景
      • 2017年,消息數(shù)過億,mongo延時變得不可控。
      • 場景讀取極其隨機,讀寫比例整體大約為 50/50。不同業(yè)務(wù)場景群讀取比例不同。但又不想對每個場景做獨立解決方案,所以他們決定基于現(xiàn)有訴求,選擇新的存儲進行數(shù)據(jù)遷移
      訴求
      • 線性可擴展性: 不希望以后重新考慮解決方案或手動重新分揀數(shù)據(jù)。
      • 自動故障轉(zhuǎn)移: 盡可能的進行自我修復(fù)
      • 維護成本低: 一旦設(shè)置好,它就能正常工作。只需在數(shù)據(jù)增長時添加更多節(jié)點即可。
      • 經(jīng)證明有效: 喜歡嘗試新技術(shù),但不能太新。
      • 可預(yù)測的性能: 延時達到一定水位就會發(fā)出警報。并且不希望緩存消息。
      • 開源: 相信自己的命運自己掌握,不想依賴第三方公司。
      實施
      • 基于以上訴求他們認為 Cassandra 是當時唯一能滿足他們要求的數(shù)據(jù)庫(后面也打臉了)
      Cassandra特性
      • Ap database
      • 是一個KKV 存儲器。主鍵由兩個 K 組成。第一個 K 是分區(qū)鍵,用于確定數(shù)據(jù)所在的節(jié)點以及在磁盤上的位置。分區(qū)中包含多條記錄,分區(qū)內(nèi)的記錄由第二個 K(即聚類鍵)標識。聚類鍵既是分區(qū)內(nèi)的主鍵,也是行的排序方式。你可以把分區(qū)看成一個有序的字典。這些屬性結(jié)合在一起,可以實現(xiàn)非常強大的數(shù)據(jù)建模。
      • 單分區(qū)大小不建議超過 100MB。Cassandra 宣稱它可以支持 2GB 分區(qū)!但雖然可以支持,但并不意味著應(yīng)該支持
      數(shù)據(jù)建模
      • 關(guān)鍵數(shù)據(jù)結(jié)構(gòu)
      CREATE TABLE messages (
        channel_id bigint,
        bucket bigint,
        message_id bigint,
        author_id bigint,
        content text,
        PRIMARY KEY ((channel_id, bucket), message_id)
      ) WITH CLUSTERING ORDER BY (message_id DESC);

       

      • 基于Cassandra的特性他們將主鍵設(shè)計成((channel_id, bucket), message_id)
        • channel_id: 服務(wù)器頻道id
        • bucket: 基于時間的數(shù)據(jù)分桶(基于他們的統(tǒng)計,大約10天的聊天消息約100MB)
        • message_id: 基于雪花算法的消息id
          • 這意味著在加載頻道時,可以告訴 Cassandra 準確掃描消息的范圍
          • 消息發(fā)布時間與bucket可以通過message_id中提取【因為message_id是基于雪花算法的】
      遷移期間與使用過程中遇到的問題
      1. 第一個遇到的就是100MB問題
        1. discord最初使用Cassandra存儲并沒有bucket概念。但在運行與遷移過程中Cassandra發(fā)出了100MB警告
        2. discord開發(fā)者通過分析歷史消息數(shù)據(jù)分布情況,定下來100MB可存儲其10天消息數(shù)據(jù),故將數(shù)據(jù)進行分桶
      2. 寫入順序問題,Cassandra的數(shù)據(jù)寫入處理邏輯是先讀后寫【本次寫入會依賴上次寫入結(jié)果】
        1. 在一個用戶編輯一條消息的同時,另一個用戶刪除了同一條消息,由于 Cassandra 寫入的所有內(nèi)容都是向上插入的,因此最終會發(fā)現(xiàn)一條記錄中除了主鍵和文本外,缺少其他所有數(shù)據(jù)
          1. 如: 在t1時間,進行了消息刪除。t2時間做了消息修改(消息體),此次修改會基于上次刪除結(jié)果,所以其他字段都為空了
          2. 他們采用的方案是啟動一個反熵進程對臟數(shù)據(jù)進行清理與刪除(可能是為了無鎖化)
      遷移后指標情況
       
      現(xiàn)在:從 Cassandra 到 ScyllaDB
      業(yè)務(wù)背景
      • 2022年,隨著業(yè)務(wù)場景和消息規(guī)模的增長, Cassandra 有 177 個節(jié)點,擁有數(shù)萬億條消息 ,Cassandra 也出現(xiàn)了嚴重的性能問題
        • 熱分區(qū)
        • 壓縮問題導(dǎo)致請求級聯(lián)延遲
        • S-T-W (java)
      訴求
      • 可解決“熱分區(qū)” 問題
      • 數(shù)據(jù)壓縮不會出現(xiàn)級聯(lián)延遲
      • 避免S-T-W
      ScyllaDB特性
      • 一般來說屬于 AP database,更加側(cè)重于可用性和分區(qū)容錯性,但是 ScyllaDB 的一致性級別是可以調(diào)整的。
      • 完全兼容 Cassandra,號稱是Cassandra CPP實現(xiàn)的替代品
        • CPP編寫,無GC,所以也就不會出現(xiàn)S-T-W
        • 相比Cassandra有更好的性能、更快的修復(fù)、通過每核分片架構(gòu)實現(xiàn)更強的工作負載隔離。
          • -- 避免出現(xiàn)級聯(lián)延遲
      ScyllaDB如何解決的壓縮問題?
      • Compaction Strategy:ScyllaDB 使用不同的算法(稱為策略)來確定何時以及如何最好地運行壓縮。該策略決定了寫入、讀取和空間放大之間的權(quán)衡。ScyllaDB Enterprise 甚至支持一種稱為增量壓縮策略的獨特方法,該方法可以顯著節(jié)省磁盤開銷。
      1. 壓縮和解壓縮并行化:ScyllaDB 使用多線程并行化壓縮和解壓縮操作,以減少壓縮和解壓縮對整體性能的影響。這樣可以更好地利用多核處理器的能力,并減少由于壓縮和解壓縮而引起的延遲。
      2. 壓縮字典緩存:ScyllaDB 使用壓縮字典緩存來提高壓縮和解壓縮的性能。字典緩存存儲了一些常見的字符串和它們的壓縮形式,這樣可以減少壓縮和解壓縮時需要傳輸?shù)臄?shù)據(jù)量,從而降低延遲。
      3. 硬件加速:ScyllaDB 利用現(xiàn)代硬件特性,如 Intel 的 CPU 壓縮指令集(Intel ISA-L),來加速壓縮和解壓縮操作。這些硬件加速技術(shù)可以顯著提高壓縮和解壓縮的性能,從而減少級聯(lián)延遲。
      缺點
      • 當以與表排序相反的順序掃描數(shù)據(jù)庫時,有反向查詢性能不足的問題
        • discord團隊識別該缺點可接受
      • 未解決“熱分區(qū)” 問題
        • 通過建立“存儲服務(wù)”進行解決
      遷移方案
      • 因為ScyllaDB完全兼容 Cassandra,所以可以直接進行數(shù)據(jù)遷移
      • 但因為其未解決“熱分區(qū)” 問題。所以discord開發(fā)者基于ScyllaDB做了業(yè)務(wù)增強實現(xiàn)來解決該問題
        • -- “存儲服務(wù)”
      遷移效果
      • 將運行 177 個 Cassandra 節(jié)點減少到僅運行 72 個 ScyllaDB 節(jié)點。每個 ScyllaDB 節(jié)點擁有 9TB 磁盤空間,高于每個 Cassandra 節(jié)點平均 4TB 的存儲空間。1774-729=60T,這么看的話他們的存儲空間也節(jié)省了一些。在 Cassandra 上獲取歷史消息的 p99 為 40-125 毫秒,而 ScyllaDB 的延遲為 15 毫秒,消息插入性能從 Cassandra 上的 5-70 毫秒 p99 到 ScyllaDB 上穩(wěn)定的 5 毫秒 p99。
      • 當然此處效果與指標存儲服務(wù)也功不可沒。下面會說存儲服務(wù)的整體設(shè)計

      6.5.1.2、 存儲服務(wù)架構(gòu)及流程

      背景
      • discord開發(fā)團隊為了解決數(shù)據(jù)查詢“熱分區(qū)”問題,Discord 采用的方案是:在 ScyllaDB 和業(yè)務(wù)服務(wù)之間加了一個中介服務(wù)(Rust 語言編寫),它不包含任何業(yè)務(wù)邏輯,主要功能就是合并請求。
      整體架構(gòu)

       

      架構(gòu)說明
      • 存儲服務(wù)主要做了兩部分功能。合并請求與收斂請求
      • 是一個有狀態(tài) 無數(shù)據(jù) 的中介服務(wù)
      模塊設(shè)計
      合并請求
      • 如果多個用戶同時請求數(shù)據(jù)庫的同一行,那么只會查詢數(shù)據(jù)庫一次。
      • 第一個發(fā)出請求的用戶會在該服務(wù)中啟動工作任務(wù), 后續(xù)請求將檢查該任務(wù)是否存在并訂閱它, 該工作任務(wù)將查詢數(shù)據(jù)庫并將該行返回給所有訂閱者。
      收斂請求
      • 同時根據(jù)一致性 hash 將同類查詢請求,比如同一個頻道的請求,進一步收斂到中介服務(wù),這樣可以讓請求合并的效果更好。
       

      6.5.2、 消息檢索架構(gòu)流程

      背景

      • 因discord業(yè)務(wù)發(fā)展迅速,在2017年要推出消息檢索功能。其技術(shù)訴求如下
        • 經(jīng)濟高效:Discord 的核心用戶體驗是文字和語音聊天。搜索是一項附屬功能,搜索的成本不應(yīng)高于信息的實際存儲成本。
        • 自我修復(fù):需要能夠承受故障,只需極少的人為干預(yù),甚至無需人為干預(yù)。
        • 可線性擴展:就像存儲信息一樣,只需在數(shù)據(jù)增長時添加更多節(jié)點即可
        • 避免繁瑣的大型集群: 在集群中斷的情況下,只有受影響集群中包含的 消息無法用于搜索。或者一旦整個集群的數(shù)據(jù)無法恢復(fù),可以將其丟棄(系統(tǒng)可以重新索引 Discord 服務(wù)器數(shù)據(jù))。

      整體架構(gòu)

      • 基于以上背景,discord團隊最終選用es來支持消息檢索,但摒棄了es的分片能力(自行實現(xiàn)消息分區(qū)),因為使用es的分片能力以當時discord的數(shù)據(jù)量意味著要建立大型集群,這會帶來較高的維護成本與恢復(fù)成本

       

      說明

      1. 應(yīng)用層進行分區(qū),分區(qū)維度為頻道id, es采用多集群方式,不同頻道id綁定不同es集群 (小集群)
        1. 這樣特定頻道數(shù)據(jù)就會被分到單一的es集群
        2. es中采用無分片單副本的索引模式(因使用了應(yīng)用分區(qū),所以不需要es的分區(qū)功能了,副本是用于集群異常數(shù)據(jù)恢復(fù)使用)
      2. 啟動his index worker 來用于歷史消息的索引與重新索引(如es集群產(chǎn)生故障,舊集群被摘除使用新的集群需要重新索引消息)
      3. 業(yè)務(wù) 服務(wù)只負責向queue里發(fā)送消息信息,由index worker進行拉取并索引進es中
        1. 能力解偶、提升主流程性能、消峰
        2. 因檢索場景大多數(shù)都是對歷史消息進行檢索,所以queue延遲與es的近實時特性是可接受的
      4. es集群注冊到etcd中來實現(xiàn)自動發(fā)現(xiàn),然后會在redis中存儲每個集群的負載情況,檢索sdk會使用負載最低的進群進行實時綁定
      5. 綁定數(shù)據(jù)使用業(yè)務(wù)db進行關(guān)系存儲并使用redis進行緩存
        1. 因為其使用的業(yè)務(wù)db無論是cassandra還是scylladb都存在高成本讀取,所以此處做了緩存 (與其前面說的不想使用緩存有出入)
      6. 下次產(chǎn)生新的消息時,直接使用既定的綁定關(guān)系進行存儲即可

      七、結(jié)論

      通過上述對discord的調(diào)研分析,獲得的一些啟發(fā):

      功能上

      discord 對開發(fā)者提供了豐富的集成方式:機器人、api、網(wǎng)關(guān)、client RPC(亮點)、GameSDK。

      設(shè)計上

      1. discord 使用了不同的技術(shù)棧來解決技術(shù)上的訴求,思路非常開闊
        1. 使用erlang開發(fā),因其天生的actor模型,故可以完美支持其響應(yīng)式架構(gòu)達到高吞吐目的
        2. 但erlang對于某些特定場景存在性能問題,又使用rust來解決。在不變業(yè)務(wù)服務(wù)的情況通過NIF 的形式進行調(diào)用(業(yè)務(wù)無感)
        3. api入口使用python可以達到快速迭代,因為內(nèi)部服務(wù)使用golang、rust、erlang又不會產(chǎn)生較大的性能問題
      2. 單一且高負載業(yè)務(wù),可通過進程分離的形式進行優(yōu)化。各司其職,壓力分攤
        1. 消息扇出流程:發(fā)送與扇出分離
        2. 推送模塊: 接收與推送分離
      3. 用戶上線時把用戶加入公會和在線狀態(tài)進行綁定,維護了公會內(nèi)的在線用戶,消息扇出時極大的減少了消息處理量
      4. 擁抱開源,在開源基礎(chǔ)上針對業(yè)務(wù)的訴求進行優(yōu)化或增強
        1. 存儲服務(wù)解決的熱分區(qū)問題。不僅大大緩解了db壓力,還降低了架構(gòu)與業(yè)務(wù)開發(fā)復(fù)雜度 (無緩存設(shè)計)
        2. 消息檢索業(yè)務(wù),discord為了避免繁瑣的大型集群實現(xiàn)了自己的分片/分區(qū)模式
      5. 隨時保持基建可替換,降低隨著業(yè)務(wù)迭代與數(shù)據(jù)發(fā)展帶來的基建升級/演進 成本(架構(gòu)一定是隨時演進的 )
      6. 基礎(chǔ)架構(gòu)與組件可作為未來參考
        1. 響應(yīng)式架構(gòu)來提升單機吞吐量
        2. db壓力過載可通過合并請求&收斂請求的方式進行優(yōu)化,來緩解db壓力
          1. 不一定非要用于存儲,比如我們客戶端的一些非重要請求也可以作此優(yōu)化來降低帶寬使用與緩解服務(wù)器壓力
       
      posted @ 2025-01-08 14:42  房上的貓  閱讀(1145)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 亚洲熟女乱综合一区二区| 国产成人一区二区视频免费| 国厂精品114福利电影免费| 天堂亚洲免费视频| 亚洲熟妇色xxxxx欧美老妇| 国产香蕉一区二区三区在线视频| 国产自在自线午夜精品| 影音先锋女人AA鲁色资源| 日本丰满人妻xxxxxhd| 任我爽精品视频在线播放| 色综合天天综合天天综| 亚洲中文字幕无码av在线| 国产精品午夜福利清纯露脸| 洪泽县| 1000部精品久久久久久久久| 扒开粉嫩的小缝隙喷白浆视频| 久久99精品国产麻豆婷婷| 国产精品久久久久久久网| 国内不卡不区二区三区| 欧美嫩交一区二区三区| 中文字幕国产日韩精品| 中国xxx农村性视频| 少妇人妻偷人精品无码视频新浪| 亚洲理论在线A中文字幕| 视频二区中文字幕在线| 亚洲国产成熟视频在线多多| 无码人妻丝袜在线视频| 看免费的无码区特aa毛片| 欲乱人妻少妇邻居毛片| 99久re热视频这里只有精品6| 久久九九久精品国产免费直播| 国产精品无遮挡猛进猛出| 国产欧美日韩精品丝袜高跟鞋| 四虎精品视频永久免费| 天堂a无码a无线孕交| 亚洲色婷婷综合久久| 日韩中文字幕av有码| 国产人妻高清国产拍精品| 欧美日本在线| 99riav精品免费视频观看| 赣榆县|