0. Intro
在facebook的MySQL版本(以下称为MyRocks)中,RocksDB是可选的存储引擎。相比于InnoDB引擎,RocksDB的一个重要的优势是它使用更少的磁盘空间。在生产系统中,特别是用户数在亿级以上的互联网应用,磁盘空间是其中比较大的成本之一,而能够使用更少的磁盘空间的RocksDB无疑是具有吸引力的。然而在生产系统中使用新的存储引擎自然有它的潜在风险,除了通过外部的各种benchmark工具测试得到各种性能数据,全方位的内部指标可以帮助我们真正了解数据库内部正在发生的事情,对于性能调优和开发都具有指导意义。而MyRocks通过SHOW ENGINE ROCKSDB STATUS和多个INFORMATION_SCHEMA表等方式提供了较为全面的内部指标。
本文将介绍SHOW ENGINE ROCKSDB STATUS中关于STATISTICS统计值与后台线程的实现原理。在了解实现原理的基础上,便可以较容易地通过扩展功能使它更好地为我们服务。
调用SHOW ENGINE ROCKSDB STATUS指令会返回多行数据,其中包括:
调用SHOW ENGINE ROCKSDB STATUS会返回若干行数据,然而这些数据并非事先存储于某个表格中,而是通过调用位于rocksdb/ha_rocksdb.cc文件中的rocksdb_show_status函数将内存中对应的数值进行规整返回给用户。
1. STATISTICS
根据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;
- }
1.1 RocksDB的STATISTICS接口
使用STATISTICS的方法也很简单。
它的头文件位于:
- include/rocksdb/statistics.h
- monitoring/statistics.h
使用方法:
- Options options;
- options.statistics = rocksdb::CreateDBStatistics();
可选统计级别:
数据统计类型分成两种:
统计函数的接口:
获取结果的接口:
1.2 RocksDB的STATISTICS实现
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。
1.3 MyRocks的使用
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统计的过程如下:
如果定义rocksdb_stats,则调用rocksdb_stats->ToString()将统计值转化为可读的字符串;
commit_latency_stats是直方图的类型,输出对应的50%, 95%, 99%, 100%四个位点的对应的值。
假如定义了is-write-stopped或者actual-delayed-write-rate等Property变量,同样会将它们输出。
2 后台线程
通过调用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的源文件和目标文件等信息。正如文章开头提到的,了解实现原理能够使我们更好地进行扩展。
2.1 thread status的接口与实现
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
关键类:
使用方法:
通过调用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
- };
2.2 MyRocks/RocksDB的使用
在RocksDB的线程池实现中,每一个启动的后台线程都会通过调用ThreadStatusUtil::RegisterThread加入被观测的后台线程的集合中。
- ThreadPoolImpl::Impl::StartBGThreads-->BGThreadWrapper-->ThreadStatusUtil::RegisterThread
在rocksdb_show_status函数中,输出BG_THREAD的过程如下:
3. 小结
本文章介绍了SHOW ENGINE ROCKSDB STATUS指令中关于STATISTICS与BG_THREAD的相关内容。
网页标题:教你玩转MyRocks/RocksDB—STATISTICS与后台线程篇
文章链接:http://www.mswzjz.cn/qtweb/news27/368177.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能