欢迎你们前往云+社区,获取更多腾讯海量技术实践干货哦~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指令会返回多行数据,其中包括:数据结构
调用SHOW ENGINE ROCKSDB STATUS会返回若干行数据,然而这些数据并不是事先存储于某个表格中,而是经过调用位于rocksdb/ha_rocksdb.cc文件中的rocksdb_show_status函数将内存中对应的数值进行规整返回给用户。app
根据RocksDB官方相关文档介绍STATISTICS,开启STATISTICS会增长增长5%-10%额外开销。函数
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
此文已由做者受权腾讯云+技术社区发布,转载请注明文章出处