第二章 OB 儲存引擎高階技術 記憶體管理 記憶體資料落盤策略-合併和轉儲 LSM Tree 技術簡介 LSM Tree(The Log-Structured Merge-Tree)核心特 點是利用順序寫來提高寫效能 ◼ 將某個物件(Partition)中的資料按照“key-value” 形式在磁碟上有序儲存(SSTable) ◼ 資料更新先記錄在MemStore中的MemTable裡,然後 再合併(Merge)到底層的SSTable裡 ◼ SSTable和MemTable之間可以有多級中間資料,同樣以 key-value形式儲存在磁碟上,逐級向下合併 基於LSM Tree 的實踐:合併 OceanBase中最簡單的LSM Tree只有C0層(MemTable)和C1層(SSTable)。兩層資料的合併過程如下: 1. 將所有observer上的MemTable資料做大版本凍結(Major Freeze),其餘記憶體作為新的MemTable繼續使用 2. 將凍結後的MemTable資料合併(Merge)到SSTable中,形成新的SSTable,並覆蓋舊的SSTable 3. 合併完成後,凍結的MemTable記憶體才可以被清空並重新使用 合併的細化 合併按照合併的宏塊的不同,可以細化為全量合併、增量合併,漸進合併三種方式: ◼ 全量合併:合併時間長,耗費IO和CPU。把所有的靜態資料都讀取出來,和動態資料歸併,再寫到磁碟中 ◼ 增量合併:只會讀取被修改過的宏塊資料,和動態資料歸併,並寫入磁碟,對於未修改過的宏塊,則直接重用 ◼ 漸進合併:每次全量合併一部分,若干輪次後整體資料被重寫一遍 基於LSM Tree 的實踐:轉儲 為了解決2層LSM Tree合併時引發的問題(資源消耗大,記憶體釋放速度慢等),OB引入了“轉儲”機制(C1層): ◼ 將MemTable資料做小版本凍結(Minor Freeze)後寫到磁碟上單獨的轉儲檔案裡,不與SSTable資料做合併 ◼ 轉儲檔案寫完之後,凍結的MemTable記憶體被清空並重新使用 ◼ 每次轉儲會將MemTable資料與前一次轉儲的資料合併(Merge),轉儲檔案最終會合併到SSTable中 分層轉儲 為了最佳化轉儲越來越慢的問題,引入了“分層轉儲”機制: ◼ 多層compaction策略:新增L0 層:被凍結的MemTable 會 直接flush 為Mini SSTable,可同時存在多個Mini SSTable。 ◼ 架構變化: 3層Vs 4層 ⚫ 3層架構:memtable + minor sstable(L1) + major sstable (L2) ⚫ 4層架構:memtable + mini sstable(L0) + minor sstable(L1) + major sstable (L2) ◼ 引數minor_compact_trigger 控制L0層Mini SSTable 總數 ◼ 引數major_compact_trigger 控制memtable dump flush次 數達到時觸發major compaction -------------------------------------------------------------- 轉儲的基本概念 轉儲功能的引入,是為了解決合併操作引發的一系列問題 ◼ 資源消耗高,對線上業務效能影響較大 ◼ 單個租戶MemStore使用率高會觸發叢集級合併,其它租戶成為受害者 ◼ 合併耗時長,MemStore記憶體釋放不及時,容易造成MemStore滿而資料寫入失敗的情況 轉儲的基本設計思路 ◼ 每個MemStore觸發單獨的凍結(freeze_trigger_percentage)及資料合併,不影響其它租戶 ◼ 也可以透過命令為指定租戶、指定observer、指定分割槽做轉儲 ◼ 只和上一次轉儲的資料做合併,不和SSTable的資料做合併 轉儲相關引數 minor_freeze_times ◼ 控制兩次合併之間的轉儲次數,達到此次數則自動觸發合併(Major Freeze) ◼ 設定為0表示關閉轉儲,即每次租戶MemStore使用率達到凍結閾值(freeze_trigger_percentage)都直接觸發叢集合併 minor_merge_concurrency ◼ 併發做轉儲的分割槽個數;單個分割槽暫時不支援拆分轉儲,分割槽表可加快速度 ◼ 併發轉儲的分割槽過少,會影響轉儲的效能和效果(比如MemStore記憶體釋放不夠快) ◼ 併發轉儲的分割槽過多,同樣會消耗過多資源,影響線上交易的效能 【轉儲適用的場景】 轉儲功能比較適用於以下場景 1. 批處理、大量資料匯入等場景,寫MemStore的速度很快,需要MemStore記憶體儘快釋放 2. 業務峰值交易量大,寫入MemStore的資料很多,但又不想在峰值時段觸發合併(Major Freeze),希望能將合併延後 【轉儲場景的常用配置方法】 1. 減小freeze_trigger_percentage的值(比如40),使MemStore儘早釋放,進一步降低MemStore寫滿的機率 2. 增大minor_freeze_times的值,儘量避免峰值交易時段觸發合併(Major Freeze),將合併的時機延後到交易低谷時段的每日合併(major_freeze_duty_time) 轉儲對資料庫的影響 轉儲的優勢 ◼ 每個租戶的轉儲不影響observer上其它的租戶,也不會觸發叢集級轉儲,避免關聯影響 ◼ 資源消耗小,對線上業務效能影響較低 ◼ 耗時相對較短,MemStore更快釋放,降低發生MemStore寫滿的機率 轉儲的副作用 ◼ 資料層級增多,查詢鏈路變長,查詢效能下降 ◼ 冗餘資料增多,佔用更多磁碟空間 手動觸發轉儲 ALTER SYSTEM MINOR FREEZE [{TENANT[=] (‘tt1' [, 'tt2'...]) | PARTITION_ID [=] 'partidx%partcount@tableid‘}] [SERVER [=] ('ip:port' [, 'ip:port'...])]; ◼ 可選的控制引數 ⚫ tenant : 指定要執行minor freeze的租戶 ⚫ partition_id : 指定要執行minor freeze的partition ⚫ server : 指定要執行minor freeze的observer ◼ 當什麼選項都不指定時,預設對所有observer上的所有租戶執行轉儲 ◼ 手動觸發的轉儲次數不受引數minor_freeze_times的限制,即手動觸發的轉儲次數即使超過設定的次數,也不會觸 發合併(Major Freeze) 檢視轉儲記錄 MemStore使用率達到freeze_trigger_percentage而觸發的租戶級轉儲,在__all_server_event_history表中 轉儲相關引數 major_compact_trigger /minor_freeze_times • 控制兩次合併之間的轉儲次數,達到此次數則自動觸發合併(Major Freeze)。 • 設定為 0表示關閉轉儲,即每次租戶MemStore使用率達到凍結閾值(freeze_trigger_percentage) 都直接觸發叢集合併。 minor_merge_concurrency • 併發做轉儲的分割槽個數;單個分割槽暫時不支援拆分轉儲,分割槽表可加快速度。 • 併發轉儲的分割槽過少,會影響轉儲的效能和效果(比如MemStore記憶體釋放不夠快)。 • 併發轉儲的分割槽過多,同樣會消耗過多資源,影響線上交易的效能。 OB合併觸發方式-定時合併 由major_freeze_duty_time引數控制定時合併時間,可以修改引數控制合併時間: alter system set major_freeze_duty_time='02:00'; OB合併觸發方式-MemStore使用率達到閾值自動合併 當租戶的MemStore記憶體使用率達到freeze_trigger_percentage引數的值, 並且轉儲的次數已經達到了minor_freeze_times引數的值,會自動觸發合併。 ◼ 透過查詢(g)v$memstore檢視來檢視各租戶的memstore記憶體使用情況 ◼ 查轉儲次數:gv$memstore, __all_virtual_tenant_memstore_info 中freeze_cnt 列 OB合併觸發方式-手動合併 可以在"root@sys"使用者下,透過以下命令發起手動合併(忽略當前MemStore的使用率): alter system major freeze; ◼ 合併發起以後,可以在"oceanbase"資料庫裡用以下命令檢視合併狀態: select * from __all_zone; 或者select * from __all_zone where name = 'merge_status'; 三種合併觸發方式 • 定時合併 (自動合併) • MemStore使用率達到閾值自動合併 (自動合併) • 手動合併 OB合併方式:MemStore使用率達到閾值自動合併 當租戶的 MemStore記憶體使用率達到freeze_trigger_percentage引數的值, 並且轉儲的次數已經達到了 major_compact_trigger/minor_freeze_times引數的值,會自動觸發合併: • 透過查詢(g)v$memstore檢視來檢視各租戶的memstore記憶體使用情況。 • 可以修改以下引數的值來影響觸發合併的時機: alter system set freeze_trigger_percentage = 40; alter system set major_compact_trigger = 100; OceanBase每日合併策略 合併排程 手動合併自動合併 自動輪轉合併自動非輪轉合併 智慧輪轉合併指定順序的輪轉合併 可透過以下幾項控制每日合併的策略 ◼ enable_manual_merge: OB的配置項, 指示是否開啟手動合併 ◼ enable_merge_by_turn: OB的配置項, 指示是否開啟自動輪轉合併 ◼ zone_merge_order: 指定自動輪轉合 並的合併順序 OB輪轉合併示例 假設叢集中的設定是zone_merge_order = 'z1,z2,z3,z4,z5',zone_merge_concurrency = 3,一次輪轉合併的大概 過程如下: 合併版本 設定SSTable中保留的資料合併版本個數 ◼ 由引數max_kept_major_version_number控制,預設值為2。 ◼ 調大引數值可以保留更多歷史資料,但同時佔用更多的儲存空間。 ◼ 在hint中利用frozen_version(<major_version>)指定歷史版本。 設定輪轉合併順序 • 合併開始前,透過引數zone_merge_order設定合併順序;只對輪轉合併有效。 • 場景舉例 假設叢集中有三個zone,分別是z1,z2,z3,想設定輪轉合併的順序為"z1 -> z2 -> z3",步驟如下: alter system set enable_manual_merge = false; -- 關閉手動合併 alter system set enable_merge_by_turn = true; -- 開啟輪轉合併 alter system set zone_merge_order = 'z1,z2,z3'; -- 設定合併順序 • 取消自定義的合併順序 alter system set zone_merge_order = ''; -- 取消自定義合併順序 合併注意事項 合併超時時間 • 由引數zone_merge_timeout定義超時閾值;預設值為'3h'(3個小時)。 • 如果某個ZONE的合併執行超過閾值,合併狀態被設定為TIMEOUT。 空間警告水位 • 由引數data_disk_usage_limit_percentage定義資料盤空間使用閾值,預設值90。 • 當資料盤空間使用量超過閾值後,合併任務列印ERROR警告日誌,合併任務失敗;需要儘快擴大資料盤物理空 間,並調大data_disk_usage_limit_percentage引數的值。 • 當資料盤空間使用量超過閾值後,禁止資料遷入。 檢視合併記錄和狀態: __all_rootservice_event_history表,檢視合併記錄: __all_zone表, 檢視當前合併狀態: 小結 ◼ OB的LSMTree可以分為C0層(MemTable)、C1層(Minor SSTable)、C2層(Major SSTable) ◼ OB記憶體透過雙索引結構和資料壓縮,提高資料的查詢效能 ◼ 合併和轉儲之前,都需要做一次凍結,然後根據引數設定決定凍結之後是轉儲還是合併 ◼ 合併可以細分為全量合併、漸進合併、增量合併三種方式,同一個資料庫,這三種方式對資源的消耗程度遞減 ◼ 為了最佳化轉儲越來越慢的問題,引入了“分層轉儲”機制,為了提高轉儲速度,加快記憶體釋放速度,被凍結的 MemTable 會直接flush 為Mini SSTable ◼ 輪轉合併可以輪流為每份副本單獨做合併,減少業務影響,但同時也存在合併時間變長、切主過程中影響長連線等 問題 ◼ 合併和轉儲特點的比較,兩者互補共同組成了OB資料完整的落盤策略