歡迎你們前往雲+社區,獲取更多騰訊海量技術實踐乾貨哦~mysql
做者:騰訊雲數據庫內核團隊git
原文標題:【騰訊雲CDB】教你玩轉MyRocks/RocksDB—STATISTICS與後臺線程篇github
在facebook的MySQL版本(如下稱爲MyRocks)中,RocksDB是可選的存儲引擎。相比於InnoDB引擎,RocksDB的一個重要的優點是它使用更少的磁盤空間。在生產系統中,特別是用戶數在億級以上的互聯網應用,磁盤空間是其中比較大的成本之一,而可以使用更少的磁盤空間的RocksDB無疑是具備吸引力的。然而在生產系統中使用新的存儲引擎天然有它的潛在風險,除了經過外部的各類benchmark工具測試獲得各類性能數據,全方位的內部指標能夠幫助咱們真正瞭解數據庫內部正在發生的事情,對於性能調優和開發都具備指導意義。而MyRocks經過SHOW ENGINE ROCKSDB STATUS和多個INFORMATION_SCHEMA表等方式提供了較爲全面的內部指標。sql
本文將介紹SHOW ENGINE ROCKSDB STATUS中關於STATISTICS統計值與後臺線程的實現原理。在瞭解實現原理的基礎上,即可以較容易地經過擴展功能使它更好地爲咱們服務。數據庫
調用SHOW ENGINE ROCKSDB STATUS指令會返回多行數據,其中包括:bash
調用SHOW ENGINE ROCKSDB STATUS會返回若干行數據,然而這些數據並不是事先存儲於某個表格中,而是經過調用位於rocksdb/ha_rocksdb.cc文件中的rocksdb_show_status函數將內存中對應的數值進行規整返回給用戶。數據結構
根據RocksDB官方相關文檔介紹STATISTICS,開啓STATISTICS會增長增長5%-10%額外開銷。app
STATISTICS統計值記錄着RocksDB引擎全部線程的全部操做的各種count/time的累加。RocksDB引擎在它的各種操做如Put/Get/Delete中的代碼都設立了不少埋點。函數
以函數GetEntryFromCache爲例,它的做用是返回可用的block cache。特別地,能夠看到statistics是GetEntryFromCache和block_cache->Lookup的一個參數。沒錯,就是靠着statistics這個參數它處處收集數據。 當有可用的block cache時,調用了三次RecordTick爲其中三個統計值增長計數;沒有可用的block cache,一樣也爲BLOCK_CACHE_MISS和block_cache_miss_ticker增長計數。工具
Cache::Handle* GetEntryFromCache(Cache* block_cache, const Slice& key,
Tickers block_cache_miss_ticker,
Tickers block_cache_hit_ticker,
Statistics* statistics) {
auto cache_handle = block_cache->Lookup(key, statistics);
if (cache_handle != nullptr) {
PERF_COUNTER_ADD(block_cache_hit_count, 1);
// overall cache hit
RecordTick(statistics, BLOCK_CACHE_HIT);
// total bytes read from cache
RecordTick(statistics, BLOCK_CACHE_BYTES_READ,
block_cache->GetUsage(cache_handle));
// block-type specific cache hit
RecordTick(statistics, block_cache_hit_ticker);
} else {
// overall cache miss
RecordTick(statistics, BLOCK_CACHE_MISS);
// block-type specific cache miss
RecordTick(statistics, block_cache_miss_ticker);
}
return cache_handle;
}複製代碼
使用STATISTICS的方法也很簡單。
它的頭文件位於:
include/rocksdb/statistics.h
monitoring/statistics.h複製代碼
使用方法:
Options options;
options.statistics = rocksdb::CreateDBStatistics();複製代碼
可選統計級別:
數據統計類型分紅兩種:
統計函數的接口:
獲取結果的接口:
RocksDB實現了StatisticsImpl類,繼承了Statistics的接口。
主要接口:
成員變量:
這裏的TickerInfo和HistogramInfo類型的數據結構是類似的:一個線程局部的counter或者time;加上一個非線程局部的統計值用來累加counter或者time。
TickerInfo類型包含兩個參數:
ThreadLocalPtr類型(真實類型ThreadTickerInfo)的thread_value,包含:
ThreadLocalPtr類型(真實類型ThreadHistogramInfo)的thread_value,包含:
事實上,STATISTICS相關實現是比較巧妙的,也是使用STATISTICS僅增長5%-10%的關鍵。爲了不線程間共享數據致使CPU的cache頻繁失效,merged_sum和merged_hist初始化時都是空的,並且當且僅當線程退出時,才調用mergeThreadValue函數將TickerInfo和HistogreamInfo中的線程局部變量累加到merged_sum和merged_hist。
MyRocks使用了RocksDB提供的接口進行數據統計。經過聲明瞭變量rocksdb_stats,而且隨着RocksDB引擎啓動時經過rocksdb_init_func函數進行初始化。
rocksdb_stats = rocksdb::CreateDBStatistics();
rocksdb_db_options->statistics = rocksdb_stats;複製代碼
除了使用全部RocksDB引擎層的統計,MyRocks還經過定義了
commit_latency_stats = new rocksdb::HistogramImpl();複製代碼
在rocksdb_commit_by_xid和rocksdb_commit兩個函數中經過計時的方式,統計了每一次commit所花費的時間。
rocksdb::StopWatchNano timer(rocksdb::Env::Default(), true);
...
commit_latency_stats->Add(timer.ElapsedNanos() / 1000);複製代碼
在rocksdb_show_status函數中,輸出Statistics統計的過程以下:
經過調用SHOW ENGINE ROCKSDB STATUS能夠獲得與BG_THREADS相關結果,它的輸出結果相似於:
Type: BG_THREADS
Name: 140173379593984
Status:
thread_type: Low Pri##
cf_name: default
operation_type: Compaction
operation_stage: CompactionJob::ProcessKeyValueCompaction
elapsed_time_ms: 6172.244 ms
BaseInputLevel: 0
BytesRead: 992806363
BytesWritten: 992071408
IsDeletion: 0
IsManual: 0
IsTrivialMove: 0
JobID: 1936
OutputLevel: 5
TotalInputBytes: 1586832446
state_type:複製代碼
能夠看到較多的信息量:這個線程正在進行Compaction,處於CompactionJob::ProcessKeyValueCompaction階段,已經耗時6172.244 ms,讀取的字節數爲992806363,寫出的字節數爲992071408。然而並不包括可能感興趣的正在進行Compaction的源文件和目標文件等信息。正如文章開頭提到的,瞭解實現原理可以使咱們更好地進行擴展。
MyRocks中的SHOW ENGINE ROCKSDB STATUS指令展現BG_THREAD的機制使用了RocksDB中關於thread status的接口。
它的頭文件位於:
include/rocksdb/env.h
include/rocksdb/thread_status.h
util/thread_operation.h
monitoring/thread_status_updater.h
monitoring/thread_status_util.h複製代碼
關鍵類:
ThreadStatusUpdater:存儲了各自後臺線程的狀態和全部後臺線程狀態的指針。 ThreadStatusUtil:該類只有靜態變量和靜態方法,推薦經過該類的方法去更新ThreadStatusUpdater中的狀態。
使用方法:
經過調用env的GetThreadList()函數能夠得到當先後臺線程的狀態,狀態的狀態值存放於一個vector中。將其中的內容展示出來,相似於下圖:
從代碼中能夠看到,實現thread status的目的展現flush和compaction的運行狀態。固然,咱們也能夠將用戶線程的狀態存儲到thread status,經過調用SHOW ENGINE ROCKSDB STATUS指令展現。
特別地,能夠看到compaction特有的狀態值有:
enum CompactionPropertyType : int {
COMPACTION_JOB_ID = 0,
COMPACTION_INPUT_OUTPUT_LEVEL,
COMPACTION_PROP_FLAGS,
COMPACTION_TOTAL_INPUT_BYTES,
COMPACTION_BYTES_READ,
COMPACTION_BYTES_WRITTEN,
NUM_COMPACTION_PROPERTIES
};複製代碼
flush特有的狀態值有:
enum FlushPropertyType : int {
FLUSH_JOB_ID = 0,
FLUSH_BYTES_MEMTABLES,
FLUSH_BYTES_WRITTEN,
NUM_FLUSH_PROPERTIES
};複製代碼
在RocksDB的線程池實現中,每個啓動的後臺線程都會經過調用ThreadStatusUtil::RegisterThread加入被觀測的後臺線程的集合中。
ThreadPoolImpl::Impl::StartBGThreads-->BGThreadWrapper-->ThreadStatusUtil::RegisterThread複製代碼
在rocksdb_show_status函數中,輸出BG_THREAD的過程以下:
本文章介紹了SHOW ENGINE ROCKSDB STATUS指令中關於STATISTICS與BG_THREAD的相關內容。
【騰訊雲CDB】源碼分析 · MySQL binlog組提交和Multi-Threaded-Slave
此文已由做者受權雲加社區發佈,轉載請註明文章出處;