頂級大廠Quora如何優化資料庫性能?

来源:https://www.cnblogs.com/JavaEdge/archive/2023/11/29/17866096.html
-Advertisement-
Play Games

Quora 的流量涉及大量閱讀而非寫入,一直致力於優化讀和數據量而非寫。 0 資料庫負載的主要部分 讀取 數據量 寫入 1 優化讀取 1.1 不同類型的讀需要不同優化 ① 複雜查詢,如連接、聚合等 在查詢計數已成為問題的情況下,它們在另一個表中構建了計數,以便它們可以直接讀取計數值而非計算計數。 ② ...


Quora 的流量涉及大量閱讀而非寫入,一直致力於優化讀和數據量而非寫。

0 資料庫負載的主要部分

  • 讀取
  • 數據量
  • 寫入

1 優化讀取

1.1 不同類型的讀需要不同優化

① 複雜查詢,如連接、聚合等

在查詢計數已成為問題的情況下,它們在另一個表中構建了計數,以便它們可以直接讀取計數值而非計算計數。

② 大型掃描

他們使用 LIMIT 改變它或使用分頁

③ 模式與查詢之間不匹配

若:

  • 無很好的索引
  • 或索引沒有足夠的列
  • 或索引中的列順序對查詢來說不是最佳

則查詢可能很慢,可能對資料庫造成很大負載。

這種情況下,通常會修改索引以對查詢進行優化。 有時查詢也可修改以對索引進行優化。如:

  • 刪除 select 子句中不必要的列(特別是索引中不存在的列)
  • 刪除 order by 子句,改為在客戶端上排序(MySQL CPU 一般比客戶端 CPU 更寶貴)
  • 若該查詢提供的功能不再重要,可完全刪除查詢

1.2 高 QPS 查詢

即使使用了優化的 SQL 和良好的模式,高 QPS查詢也給資料庫帶來很大負載。有時可能表示緩存效率低下(甚至沒緩存)。

① 低效的緩存是否導致了高 QPS 查詢?

緩存通常用於減少資料庫 QPS。緩存鍵的選擇可以極大地影響緩存的效率:

  • 若緩存鍵過於具體或狹窄,可能導致資料庫出現高 QPS
  • 若緩存鍵太寬泛,每次查詢都會從資料庫中拉取大量數據

② 對用戶語言表的查詢

我們有一個表跟蹤用戶使用的語言信息。通常會查詢資料庫以查看用戶 U 是否使用語言 L。使用(uid,language_id)作為緩存鍵看起來合理。如緩存未命中,將為該 uid 和 language_id 查詢資料庫表。

因此,將緩存鍵更改為僅使用 uid 確實有意義,緩存值將是有關用戶使用的所有語言的信息。

以上述方式更改緩存鍵,會增加從庫表中每次查詢獲取的數據量,但它將 QPS 減少超過 90%。大多數用戶只使用一或幾種語言。 因此,大多數情況,新的查詢並沒有拉取比以前更多的數據,這是一個顯然的優化!

③ 查詢 A2A(ask to answer)表

這裡我們處理 3 個實體間的關係,即用戶(誰提問或關註問題)、問題和回答者,這比 2 個實體之間的關係更不常見。

通常產品邏輯是查詢:

  • 用戶已請求過的所有回答者,使用緩存鍵 (question_id, user_id)
  • 請求過相同回答者回答一個問題的所有用戶,使用緩存鍵 (question_id, answerer_id)

綜上,A2A 表的 QPS 非常高,這意味著上述緩存效果並不明顯。上述兩個緩存都在使用 2 個實體作為緩存鍵question_id 和 user_id(可以是提問者或回答者)。

潛在緩存鍵數量巨大,因為它是問題數和用戶數的乘積,其中只有很少的組合實際上在表中有數據。所以它可看作一個稀疏的數據集,有2維。

大多數問題的 A2A 請求數量相對較少,但有少數問題的 A2A 數量要多得多。因此,添加額外緩存,該緩存包含問題的 A2A,最多限製為 N 個,以便我們捕獲大多數問題。 該緩存的鍵只是 question_id。 如緩存列表大小小於N,我們知道緩存是完整的。 否則,緩存不完整,我們不會使用緩存。

這額外緩存幫助顯著減少 A2A 表上的 QPS(在 50% 到 66% 的範圍內)。 還對產品邏輯進行了其他更改,以提高效率,但 QPS 的減少大部分來自額外緩存。

1.3 一維數據集中的稀疏數據

Quora 在緩存方面經常遇到的另一個問題是:稀疏一維數據集。如可能需要查詢資料庫,看某問題是否需重定向到另一問題(如同一個問題被重新發佈,就可能發生這種情況)。

絕大多問題不需要重定向,所以 Quora 只會獲取幾個“重定向”,而大量“不重定向”。

當他們只是緩存了 question_id ,緩存中就會填滿不用,只有幾個重定向。 這在緩存中占用大量空間,且由於“重定向”數量如此稀疏,也會導致大量緩存未命中。

相反,他們開始緩存範圍。 如 question id 123–127的任一問題都沒重定向,那麼他們會將該範圍緩存為所有問題均為 No,而不是緩存每個單獨的 question id。

這大大降低此類查詢的資料庫負載,QPS 下降 90%。

2 優化表占用空間

由於以下幾個原因,表大小很重要:

  • 存儲更多數據的成本更高
  • 隨表增長,適應資料庫緩衝池的數據百分比會變小,即IO會逐漸增加,性能會逐漸下降
  • 備份和恢復時間會隨表大小線性增長。雖然備份是從 MySQL 副本完成的,但我們也會從副本讀數據。在備份期間,MySQL副本性能略有下降
  • 隨表增長,備份大小也在增長,導致備份存儲成本隨時間增長

顯然,對不需要永久存儲的數據,制定最佳保留策略有助減少表大小 —— 使用 MyRocks 減少表大小

  • 有一些表對於表所有者來說無法接受任何數據的刪除。為此研究使用 MyRocks 來減小空間使用
  • MySQL 中的表可能使用更複雜的模式和查詢。 所以他們希望謹慎使用 MyRocks。 作為分片項目的一部分,已對 MySQL 中最大的表進行分片,這是在 MySQL 在 Quora 的分片中記錄
  • 此表是基於自增列範圍進行分片的,與基於時間的分片接近,因為自增列值隨時間增加
  • 大多數查詢訪問最近的分片。 包含 18 個月以上舊數據的較舊分片對日常業務相對不太關鍵

因此,他們決定按如下方式將較舊的分片移至 MyRocks。 有個工具可將 MySQL 表從一個 MySQL 主伺服器移動到另一個主伺服器。 每個分片實際上是一個 MySQL 表。 他們能夠使用該工具按如下方式將包含舊數據的 MySQL 分片轉換為 MyRocks 分片:

  • 在 MyRocks 主伺服器上使用相同的模式創建一個新的空表,但使用 RocksDB 存儲引擎
  • 使用該工具複製數據並從 MySQL 主伺服器重放binlog(二進位日誌)到 MyRocks 主伺服器。 (該工具已被修改為跳過在目標主機上創建表,因為它已經在前一步中創建過。)
  • 執行陰影讀取測試以驗證 MyRocks 分片返回的結果與 MySQL 分片的結果相同。
  • 將流量切換到 MyRocks 分片。 (這類似於我們在將 MySQL 表從一個 MySQL 主伺服器移動到另一個 MySQL 主伺服器時執行的切換。 源主機上的表被重命名以停止新寫入,然後在重放趕上後,該表的流量會切換到目標主機。)
  • 對於非鍵值存儲表使用 MyRocks 是我們的一個重大舉措。 根據表的不同,空間使用量的減少也有差異。 對於上面提到的第一個表,我們看到每個已移動的分片使用的空間減少了 80% 以上! 對於第二個表,我們看到每個已移動的分片使用的空間只減少了約 50-60%

3 優化寫入

有時複製延遲警報,因為 MySQL複製預設情況下會在副本上串列重放主伺服器上的併發寫。在主伺服器上並行寫入而在副本上串列重放寫入並不適合擴展寫入,特別是如果他們使用帶多核 CPU 的機器。

MySQL 提供兩種方法實現這點,如下所述。兩種方法中都需使用 slave_parallel_workers 配置並行度。

  1. slave_parallel_type=LOGICAL_CLOCK(從 MySQL 8.0.26 開始為 replica_parallel_type)
  • MySQL 5.7開始可用。即使所有表都在同一邏輯資料庫中,它也可以在副本上並行執行寫。
  1. slave_parallel_type=DATABASE(從 MySQL 8.0.26 開始為 replica_parallel_type)
  • 這需要表位於多個邏輯資料庫中才能並行執行寫
  • 增強存儲在 zk 中的資料庫配置,以跟蹤表所在的邏輯資料庫。將此信息保存在 zk 而非代碼庫或靜態配置中,允許動態更改現有表的邏輯資料庫。大多數表都位於預設邏輯資料庫,因此只需要為不在預設邏輯資料庫中的表保留此信息
  • MySQL alter table 語句可用於更改表的邏輯資料庫,如 alter table <logical_db1>.table rename <logical_db2>.mytable。 它不複製數據,只是將底層 ibd 文件從一個目錄移動到另一個目錄,速度很快。移動表後,我們還會在 zk 更新資料庫配置,以便應用程式可找到該表
  • 他們將一個表移動到其自己的邏輯資料庫並啟用並行複製。有助減少包含該表的 MySQL 副本上的複製延遲。

4 結論

學習了世界級大廠如何使用各種技術的組合來優化資料庫中的讀取、寫入和空間使用。你們公司如何優化的呢?歡迎和我一起交流。

參考:

本文由博客一文多發平臺 OpenWrite 發佈!


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

-Advertisement-
Play Games
更多相關文章
  • 無論你做什麼,都要相信自己可以做到,因為你的潛力是無限的。 把父組件的狀態變成屬性傳遞給子組件,子組件接受這個屬性,聽命於父組件。這個子組件就是叫做受控組件。在受控與非受控組件有兩種理解方案,第一:狹義上的受控與非受控,就是我們在表單中的受控與非受控組件。第二:廣義上的受控與非受控組件,就是 Rea ...
  • 不要因為別人的評價而改變自己的想法,因為你的生活是你自己的。 1. React 中 Ref 的應用 1.1 給標簽設置 ref 給標簽設置 ref,ref="username", 通過 this.refs.username 可以獲取引用的標簽,ref 可以獲取到應用的真實 Dom 節點。但是 thi ...
  • 作為一個開放式的跨端跨框架解決方案,Taro 在大量的小程式和 H5 應用中得到了廣泛應用。本文將為大家提供一些小程式開發的最佳實踐,幫助大家最大程度地提升小程式應用的性能表現。 ...
  • typora-copy-images-to: media ES5和字元串 一、ES5的語法 js在產生的時候,年代比較早,當時的web需求比較少,所以剛開始的js功能比較少,語法沒有特別嚴謹。隨著時代的發展和web應用的普及,js需要更多的功能,以及更嚴謹的語法,所以,js會有版本的升級。第一版的j ...
  • big.js,一個小型、快速的用於任意精度的十進位算術的JavaScript 庫。 big.js 用於解決平常項目中進行算術運算時精度丟失引起的結果不准確的問題。和 big.js 類似的兩個庫 bignumber.js 和 decimal.js 也都是出自同一作者(MikeMcl)之手。 作者在 這 ...
  • 設計模式一直是程式員談論的“高端”話題之一,總有一種敬而遠之的心態。在瞭解後才知道在將函數作為一等對象的語言中,有許多需要利用對象多態性的設計模式,比如單例模式、 策略模式等,這些模式的結構與傳統面向對象語言的結構大相徑庭,實際上已經融入到了語言之中,我們可能經常使用它們,只是不知道它們的名字而已。 ...
  • Batrix企業能力庫,是京東物流戰略級項目-技術中台架構升級項目的基礎底座。致力於建立企業級業務復用能力平臺,依托能力復用業務框架Batrix,通過通用能力/擴展能力的定義及復用,靈活支持業務差異化場景的快速能力編排組裝,從而通過技術驅動的方式助力業務整體交付吞吐率。本文重點為大家介紹交易域如何使... ...
  • 當使用Spring Boot整合HikariCP時,您可以更加詳細地配置和優化連接池以獲得更好的性能。以下是更詳細的步驟和示例代碼: 步驟1:創建Spring Boot項目 您可以使用Spring Initializr(https://start.spring.io/)創建一個新的Spring Bo ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...