【OceanBase診斷調優】—— KVCache 排查手冊

原文鏈接:OceanBase分布式數據庫-海量數據 筆筆算數

本文介紹 KVcache 相關問題的排查方法。

KVCache 相關概念

在進行排查前,需要了解幾個概念。

  • pin

    一個 cache 塊 ( memblock ) 被 pin 住,表示它正在被引用。

    cache 的由多個定長的塊組成,每個塊稱為一個 memblock 。每個 memblock 中存放了多個 KV ,使用者通過 KV 指針來讀取 KV 。容易理解,在使用指針的過程中,需要保證指針的安全,也即需要 pin 住存放 KV 的 memblock ,保證它不被釋放。cache 內部通過引用計數來實現,cache 每向外吐出一個 KV 指針,都要對 KV 所在的 memblock 的引用計數加 1 ( pin 住這個 memblock ) ,當不再使用 KV 指針時,引用計數減 1 。也就是說,當引用計數大于 0 時,說明有人正在讀其中的內存,那這個 memblock 就不能被釋放,反之如果等于 0 ,則釋放是安全的。

    簡而言之,如果一個 memblock 被 pin 住,那么它不能被釋放。

  • sync wash

    sync wash 指 cache 騰出自身內存給租戶使用的過程。 從 1 可知,如果一個 memblock 沒有被 pin ,那么它是可以被釋放的。sync wash 就是 cache 找到沒有被 pin 的 memblock ,釋放內存,騰給租戶使用。

  • cache 大小無上限

    cache 的大小在一個租戶內是無上限的。 為了最大化利用租戶內存,在租戶內不限制 cache 的大小,理論上 cache 最大可以占滿一個租戶的內存。但是 cache 的內存比較特殊,在租戶需要內存時,會觸發 cache 的 sync wash ,騰出內存給租戶使用。

常見問題

ret=-4273 can not find enough memory block to wash

首先 4273 不是 cache 的問題,4273 報錯表示在 sync wash 過程中發現 cache 中所有的 memblock 都被 pin 了,沒有內存可以釋放。 導致 4273 的原因可能有:

  • cache 本身已經被榨干了,沒有內存可以 wash ,所以就找不到不被 pin 的 memblock。

  • cache 本身還有內存,但是都被 pin 住了,無法 wash 出來;這個原因又分為兩種情況:

    • 確實有需要較多 cache 的 SQL 在執行。
    • cache handle 引用計數有泄漏。

排查的思路就是逐步確認是哪個原因導致的 4273 ,步驟如下:

  1. 查看當時 cache 的大小。

    * 通過 MEMORY 日志,memory 日志可以看到租戶的 cache_hold ,這個字段記錄了 cache 的總大小。
    * 通過 CACHE 日志,可以看到當時各個 cache 的大小。
    * 通過虛擬表 `__all_virtual_kvcache_info`,各版本都有,但是是實時數據,需要在案發時查詢。
    

    如果此時 cache 大小很少,說明此時 cache 本身已經被榨干,wash 不出內存符合預期,應該查看當時租戶的內存分布,看看其他 mod 是否符合預期,否則進入第二步。

  2. 判斷是否存在泄漏。

    這一步是通過查看 cache 的大小能否降下來,來區分是 cache handle 引用計數有泄漏還是確實有需要較多 cache 的 SQL 在執行。

    對于 OceanBase 數據庫 V4.0 及以后版本,可以停止所有查詢后嘗試手動 flush cache ,如果 cache 能降下來,則說明沒有泄漏,是確實有需要較多 cache 的 SQL 在執行導致。

    手動 flush 需要直連到 OBServer 節點上執行,如果可以 flush 干凈 ( 可能需要手動 flush 多次 ) ,則表示沒有泄漏,對比 flush 前后?__all_virtual_kvcache_info?表中 size 的變化來判斷。也可以通過查詢?__all_virtual_kvcache_store_memblock?虛擬表來直接查看所有 memblock 引用計數,看是否有異常。

    select * from __all_virtual_kvcache_store_memblock where ... order by ref_count desc limit 10;
    

    對于 OceanBase 數據庫 V4.0 之前版本,只能通過日志查看在 4273 報錯后,cache 的大小是否降下去過,如果能降下去,則說明一定沒有泄漏,如果沒降下去過,則無法判斷。( 因為之前版本手動 flush 并不會立即釋放 cache 的內存,而是通過降低其訪問熱度,通過后臺 wash 線程慢慢刷出去。 )

    如果是較多 cache 的 SQL 在執行導致,規避方案是,將 cache 用量較大的操作分散在租戶內存壓力較小的時候執行,如果仍有報錯,嘗試對租戶內存進行擴容,增大內存。 如果是 cache handle 引用計數有泄漏導致,則需要復現問題,排查泄漏的路徑。

cache 占用內存較高

如前文所述,cache 在租戶內是無上限的,所以理論上無論 cache 占多大內存,只要能被 sync wash ,就是符合預期的。 判斷能否 sync wash 出來需要參考問題 1 中判斷 cache 大小能否降下來的方法,能降下來就是能 sync wash 出來。

cache 預熱

OceanBase 數據庫 V4.0 及以后的版本支持 cache 預熱功能,之前版本沒有此功能。 為緩解 compaction 后的性能抖動,在 compaction 時會將新生成的微塊放入 cache 中,進行預熱。 預熱并不會將所有新生成的微塊都預熱進 cache ,而是根據租戶的內存情況進行預熱。現有策略下,data block cache 使用租戶空閑內存的 5% ,index block 使用租戶空閑內存的 2% 。 data block 和 index block 按照不同的優先級被預熱進 cache ,按照中間層索引樹的等級分配不同的優先級,越接近根節點的 block 優先級越高。

wash

cache 騰出自身內存的過程稱為 wash ,cache 的 wash 行為分為同步 wash 和異步 wash 兩種。 同步 wash 就是上文提到的 sync wash,同步騰出內存,這里不再贅述。 異步 wash 由一個后臺 wash 線程完成,wash 線程會定期地根據每個租戶的內存壓力 ( 包括租戶大小、當前 cache 大小、租戶當前空閑內存等 ) 計算出租戶應該 wash 出的 cache size ,然后再根據每個 memblock 的訪問熱度從低到高 wash 。如果壓力不大,計算結果可能是 0,不做 wash ,可以根據如下日志來判斷,如果有則表示 wash 線程異步 wash 了 memblock。

COMMON_LOG(INFO, "Wash memory, ","tenant_id", wash_iter->first,"cache_size", tenant_wash_info->cache_size_,"lower_mem_limit", tenant_wash_info->lower_limit_,"upper_mem_limit", tenant_wash_info->upper_limit_,"min_wash_size", tenant_wash_info->min_wash_size_,"max_wash_size", tenant_wash_info->max_wash_size_,"mem_usage", lib::get_tenant_memory_hold(wash_iter->first),"reserve_mem", static_cast<int64_t>((static_cast<double>(tenant_wash_info->upper_limit_)) * tenant_reserve_mem_ratio_),"wash_size", tenant_wash_info->wash_size_);

wash 線程的異步 wash 實際上是減去 memblock 原始的引用計數,等待引用計數減為 0 時執行釋放,因此:

  • 異步 wash 并不能立即釋放 memblock ,需要等待不被 pin 。
  • 如果有引用計數泄漏泄漏,wash 線程一樣不能 wash memblock。

手動 flush

手動 flush cache 表示手動清理指定 cache , 命令如下,目前只能在 sys 租戶下執行,需要直連要 flush 的 OBServer 節點。

alter system flush kvcache [tenant tenant_name [cache 'cache_name']];

cache_name 可以在?__all_virtual_kvcache_info?中查到,常用的 cache_name 有 :user_block_cache、index_block_cache、user_row_cache、fuse_row_cache、bf_cache。

OceanBase 數據庫 V4.0 及以后版本,flush 包含了立即清空的功能,預期情況下,flush 之后 cache 應該是立即被清空(若內存占用太多,flush 只清理一部分內存)。如果發生 4274 的報錯,是 cache 較多導致的超時問題,再次 flush 即可。

OceanBase 數據庫 V4.0 之前版本,手動 flush 只會清除指定 cache 中 KV 的索引,索引刪除后,對應的 KV 就無法再被訪問到,其所在的 memblock 的熱度就會持續降低,等待 wash 線程將其 wash 出去。

判斷手動 flush 是否生效

無論新老版本,手動 flush 一定會清理掉全部的 kv_cnt ,可以觀察 flush 前后 kv_cnt 是否清零過來判斷手動 flush 是否生效。

select * from __all_virtual_kvcache_info where cache_name = '<cache_name>';

監控 cache handle ,排查引用計數泄漏

OceanBase 數據庫 V4.0 及之后版本,如果懷疑或確認 cache 引用計數有泄漏,可以通過如下方法診斷。

  1. binary 需要啟用 ENABLE_DEBUG_LOG 編譯選項。

  2. 打開監控,指定監控的 cache name 。

    alter system set leak_mod_to_check = 'cache_name';
    
  3. 查看泄漏 backtrace 。

    select * from __all_virtual_kvcache_handle_leak_info where tenant_id = tenant_id order by hold_count desc limit 10;
    

    在 OceanBase 數據庫 V4.3 及以后版本虛擬表更名為?__all_virtual_storage_leak_info,并且新增配置項?_storage_leak_check_mod?用于指定泄漏監控的內容。

    這里簡單介紹一下監控的實現方法。cache 對外吐出的引用計數都包含在 cache_handle 中,一個 cache_handle hold 住 1 個引用計數,所以在 cache 對外吐出 cache_handle 時,記錄一條 backtrace ,在 cache_handle reset 時,消除記錄。所以最后遺留下來未釋放的 backtrace 很大可能就是泄漏的 backtrace 。

    根據記錄方式可以知道,只要當前 cache 外部有 cache_handle ,那就會被記錄 backtrace ,所以任何路徑在持有 cache_handle 期間都會被記錄,需要抓到持有時間過長或不符合預期的堆棧才是泄漏的堆棧。

    如果事先沒有開啟 cache handle 監控,可以通過?__all_virtual_kvcache_store_memblock?虛擬表簡要確認一下問題,這張表會輸出當前 server 上所有 memblock 的信息。 (OceanBase 數據庫 V 4.3 及以后版本使用新的虛擬表)

    select * from __all_virtual_kvcache_store_memblock where ... order by ref_count desc limit 10;
    

    關注?ref_count?列,這一列表示 memblock 的當前的引用計數,目前當 memblock 沒有被引用時,這里拿到的引用計數為 2 ( 初始引用計數為 1 ,查 memblock 信息時需要先加引用計數做保護,因此為 2 ) 。在確保某 memblock 當前不會被 pin 的前提下,ref_count 大于 2 的 memblock 都可以認為有引用計數泄漏。

泄漏檢測擴展 (OceanBase 數據庫 V4.3 及以后版本)

OceanBase 數據庫 V4.3 及以后版本,新增存儲層的泄漏檢測功能,目前支持的檢測內容有 cache handle、io handle、storage iter ,同時,新增配置項?_storage_leak_check_mod?用于配置泄漏檢測的內容,有效值分別為?cache_name / all_cache / io_handle / storage_iter?,默認為空串,設定成空串或其他值時,關閉監控。

同時,__all_virtual_kvcache_handle_leak_info?虛擬表更名為?__all_virtual_storage_leak_info

檢測步驟使用新的配置和虛擬表即可:

  1. binary 需要啟用 ENABLE_DEBUG_LOG 編譯選項。

  2. 打開監控,指定監控的內容。

    alter system set _storage_leak_check_mod = 'cache_name' | 'all_cache' | 'io_handle' | 'storage_iter' ;
    
  3. 查看泄漏 backtrace。

    select * from __all_virtual_storage_leak_info where ... order by hold_count desc limit 10;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/14552.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/14552.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/14552.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HAL庫點LED燈

文章目錄 一、創建CubeMX項目操作步驟1.STM32CubeMX創建工程2.選擇芯片3.Pinout & Configuration配置4.Clock Configuration配置5.Project Manager配置 二、實驗&#xff08;一&#xff09;LED流水燈1.Keil修改代碼2.實驗現象3.keil波形仿真 &#xff08;二&#xff09;2只…

代碼隨想錄(棧和隊列)

用棧實現隊列&#xff08;Leetcode232&#xff09; package 棧和隊列;import java.util.ArrayList; import java.util.Stack; 思路&#xff1a;1、用一個棧stack2來存壓入的數&#xff0c;當要pop或peek操作時再壓入stack中&#xff0c;實現隊列順序2、不是每次pop都從stack2中…

沒有CAN硬件,在Linux下模擬使用Socket CAN

即使沒有實際的CAN硬件,我們仍然可以在Linux下使用socketcan進行模擬。這可以通過使用虛擬的CAN接口(vcan)來實現。vcan接口是Linux內核提供的虛擬CAN總線接口,適用于開發和測試socketcan應用。 以下是如何設置和使用vcan接口的步驟: 1. 加載vcan模塊 首先,你需要確保…

變量命名的藝術:讓你的代碼更具可讀性

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、引言&#xff1a;為何變量命名如此重要&#xff1f; 二、變量命名的基本規則 1. 避免數…

卷爆短劇出海:五大關鍵,由AIGC重構

短劇高溫下&#xff0c;談談AIGC的助攻路線。 短劇&#xff0c;一個席卷全球的高溫賽道。 以往只是踏著霸總題材&#xff0c;如今&#xff0c;內容循著精品化、IP化的自然發展風向&#xff0c;給內容、制作、平臺等產業全鏈都帶來新機&#xff0c;也讓短劇消費走向文化深處&am…

Docker僅需3步搭建免費私有化的AI搜索引擎-FreeAskInternet!

簡介 FreeAskInternet 是一個完全免費、私有且本地運行的搜索引擎&#xff0c;并使用 LLM 生成答案&#xff0c;無需 GPU。用戶可以提出問題&#xff0c;系統會進行多引擎搜索&#xff0c;并將搜索結果合并到ChatGPT3.5 LLM中&#xff0c;并根據搜索結果生成答案。 什么是 Fr…

重學java 39.多線程 — 線程安全

逐漸成為一個情緒穩定且安靜成長的人 ——24.5.24 線程安全 什么時候發生&#xff1f; 當多個線程訪問同一個資源時&#xff0c;導致了數據有問題&#xff0c;出現并發問題&#xff0c;數據不能及時更新&#xff0c;導致數據發生錯誤&#xff0c;出現線程安全問題 多線程安全問…

紋理映射技術在AI去衣中的藝術與科技融合

引言&#xff1a; 在數字圖像處理的世界里&#xff0c;AI去衣技術正逐步揭開其神秘的面紗。這門技術結合了深度學習的智能算法與圖形學的先進手段&#xff0c;以實現對圖像中衣物的智能識別與處理。在這一過程中&#xff0c;紋理映射技術發揮著至關重要的作用。本篇博客將深入探…

變量命名的藝術:從蛇形到駝峰

新書上架~&#x1f447;全國包郵奧~ python實用小工具開發教程http://pythontoolsteach.com/3 歡迎關注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目錄 一、蛇形命名法的魅力 二、類名和模塊名的特殊規則 三、駝峰命名法的魅力與挑戰 四、保持…

【kubernetes】探索k8s集群中kubectl的陳述式資源管理

目錄 一、k8s集群資源管理方式分類 1.1陳述式資源管理方式&#xff1a;增刪查比較方便&#xff0c;但是改非常不方便 1.2聲明式資源管理方式&#xff1a;yaml文件管理 二、陳述式資源管理方法 2.1查看版本信息 2.2查看資源對象簡寫 2.3配置kubectl自動補全 2.4node節點…

初始Java篇(JavaSE基礎語法)—— 內部類

找往期文章包括但不限于本期文章中不懂的知識點&#xff1a; 個人主頁&#xff1a;我要學編程(?_?)-CSDN博客 所屬專欄&#xff1a;JavaSE 目錄 內部類的概念 內部類的種類 使用舉例&#xff1a; 1. 靜態內部類&#xff1a; 2. 實例內部類 3. 局部內部類 4. 匿名內部…

1分鐘帶你搞定Pandas DataFrame運算

1. DataFrame之間的運算 在運算中自動對齊不同索引的數據 如果索引不對應&#xff0c;則補NaN DataFrame沒有廣播機制 導包 # 導包import numpy as npimport pandas as pd 創建 DataFrame df1 不同人員的各科目成績&#xff0c;月考一 # 創建DataFrame二維數組df1 pd.Da…

想要修改Excel表格內容,怎么移除編輯權限?

在使用Excel進行數據處理和管理時&#xff0c;我們經常會遇到需要保護工作表以防止誤操作的情況。有時可能碰到“被保護單元格不支持此功能”的提示&#xff0c;本文將詳細介紹這個問題的解決方案&#xff0c;幫助你取消單元格保護&#xff0c;使用所需的功能。 一、取消單元格…

leetcode刷題記錄:前綴和

https://labuladong.online/algo/problem-set/perfix-sum/#%E8%A7%A3%E6%B3%95%E4%BB%A3%E7%A0%81-3 適用范圍&#xff1a;快速、頻繁地計算一個索引區間內的元素之和 303 區域和檢索&#xff1a;數組不可變 https://leetcode.cn/problems/range-sum-query-immutable/ class …

【Unitydemo制作】音游制作—排行榜邏輯Json存儲

&#x1f468;?&#x1f4bb;個人主頁&#xff1a;元宇宙-秩沅 &#x1f468;?&#x1f4bb; hallo 歡迎 點贊&#x1f44d; 收藏? 留言&#x1f4dd; 加關注?! &#x1f468;?&#x1f4bb; 本文由 秩沅 原創 &#x1f468;?&#x1f4bb; 收錄于專欄&#xff1a;就業…

GQL 來了!ISO/IEC 正式發布 GQL 數據庫國際標準!

歷時四年籌備&#xff0c;超過20個國家的標準和技術專家參與制定&#xff0c;ISO/IEC GQL &#xff08;圖查詢語言&#xff09;標準于2024年4月12日正式發布&#xff01; 作為國際標準化組織&#xff08;ISO&#xff09;繼 1987年 發布SQL后&#xff0c;唯一發布的數據庫查詢語…

瑞米派Ubuntu系統移植指南-米爾RemiPi

1.概述 Linux系統平臺上有許多開源的系統構建框架&#xff0c;這些框架方便了開發者進行嵌入式系統的構建和定制化開發&#xff0c;目前比較常見的有Buildroot, Yocto, OpenEmbedded等等。 同時更多的傳統的桌面系統也加入到嵌入式環境體系中&#xff0c;如Ubuntu&#xff0c…

Marin說PCB之POC電路layout設計仿真案例---03

今天天中午午休的時候&#xff0c;我剛要打開手機的準備刷抖音看無憂傳媒的學生們的“學習資料”的時候&#xff0c;看到CSDN -APP上有提醒&#xff0c;一看原來是一位道友發的一個問題&#xff1a; 本來小編最近由于剛剛從國外回來&#xff0c;手上的項目都已經結束了&#xf…

如何制作正方形,給 placeholder 換顏色,多行省略號,純css小三角,清除浮動,清除 margin,隱藏滾動條,隱藏 number 小圖標

https://www.npmjs.com/package/sass-runtime-tool yarn add sass-runtime-tool -D # or npm i -D sass-runtime-tool use "sass-runtime-tool/all.scss" as *;// 改變 placeholder 的顏色和大小 .input {include placeholder(red) {font-size: 12px;} } /* 或者 *…

一個模板元函數來檢查一個類是否有一個特定的成員

通過創建一個模板元函數來檢查一個類是否有一個特定的成員。以下是一個例子&#xff1a; #include <type_traits>template<typename T, typename void> struct has_type_member : std::false_type {};template<typename T> struct has_type_member<T, s…