頂級大廠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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...