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指令会返回多行数据,其中包括:

STATISTICS:RocksDB引擎所有线程的所有操作的各类count/time的累加,比如rocksdb.block.cache.hit和rocksdb.db.write.micros。

BG_THREADS: 后台线程的状态。

DBSTATS: 数据库操作的统计。

CF_COMPACTION: 各个Column family进行compaction的相关指标统计。

MEMORY_STATS: 内存使用情况。

调用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 readfromcache

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);

}

returncache_handle;

}

1.1 RocksDB的STATISTICS接口

使用STATISTICS的方法也很简单。

它的头文件位于:

include/rocksdb/statistics.h

monitoring/statistics.h

使用方法:

Options options;

options.statistics= rocksdb::CreateDBStatistics();

可选统计级别:

kExceptDetailedTimers: 除去mutex等待和压缩的计时

kExceptTimeForMutex: 除去mutex等待的计时

kAll: 所有

数据统计类型分成两种:

ticker:计数,类型是64位无符号整型。用于度量counters (e.g. “rocksdb.block.cache.hit”), cumulative bytes (e.g. “rocksdb.bytes.written”) 或者 time (e.g. “rocksdb.l0.slowdown.micros”)。

histogram:统计数据的统计分布,包括***值、最小值、平均值、中位数、标准差。

统计函数的接口:

MeasureTime:函数名有歧义。实际上是把value记录到histogram中。

RecordTick:累加ticker。

获取结果的接口:

Statistics::getTickerCount:指定ticker type获得count。

Statistics::histogramData:指定Histograms type,返回一个HistogramData结构体,成员是统计值,包括***值、最小值、平均值、中位数、标准差。

Statistics::getHistogramString:指定Histograms type,返回直方图可读的字符串。

Statistics::ToString():返回可读的字符串,包括所有的ticker和histogram。

1.2 RocksDB的STATISTICS实现

RocksDB实现了StatisticsImpl类,继承了Statistics的接口。

主要接口:

getTickerCount

histogramData

getHistogramString

getAndResetTickerCount

recordTick

measureTime

ToString

成员变量:

TickerInfo tickers_[INTERNAL_TICKER_ENUM_MAX];

HistogramInfo histograms_[INTERNAL_HISTOGRAM_ENUM_MAX];

这里的TickerInfo和HistogramInfo类型的数据结构是相似的:一个线程局部的counter或者time;加上一个非线程局部的统计值用来累加counter或者time。

TickerInfo类型包含两个参数:

ThreadLocalPtr类型(真实类型ThreadTickerInfo)的thread_value,包含:

整型类型的value

指向merged_sum的指针

整型类型的merged_sum

HistogreamInfo类型包含两个参数:

ThreadLocalPtr类型(真实类型ThreadHistogramInfo)的thread_value,包含:

HistogramImpl类型的value

指向merged_hist的指针

指向merge_lock的指针

HistogramImpl类型的merged_hist

Mutex类型的merge_lock

事实上,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

关键类:

ThreadStatusUpdater:存储了各自后台线程的状态和所有后台线程状态的指针。

ThreadStatusUtil:该类只有静态变量和静态方法,推荐通过该类的方法去更新ThreadStatusUpdater中的状态。

使用方法:

将该线程的统计加入ThreadStatusUpdater:调用ThreadStatusUtil::RegisterThread

将该线程的统计从ThreadStatusUpdater删除:调用ThreadStatusUtil::UnregisterThread

其他修改thread status的函数:见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的过程如下:

通过调用GetThreadList(&thread_list)获得所有后台线程的ThreadStatus的集合。

通过遍历ThreadStatus的集合将每一个后台线程的状态依次输出。

3. 小结

本文章介绍了SHOW ENGINE ROCKSDB STATUS指令中关于STATISTICS与BG_THREAD的相关内容。

【编辑推荐】

【责任编辑:庞桂玉 TEL:(010)68476606】

点赞 0

rocksdb原理_教你玩转MyRocks/RocksDB—STATISTICS与后台线程篇相关推荐

  1. 轻松制作GIF动画!教你玩转PS时间轴之进阶技巧篇

    上一篇文章跟大家讲过PS时间轴的基础,接下来跟大家分享制作简单GIF动画的一些技巧,(文字动画.颜色渐变.咻一咻动画.模糊动画.旋转时钟以及变化的月亮等等),文章提到的动画都有提供打包下载,想学时间轴 ...

  2. rocksdb原理_[转]Rocksdb Compaction原理

    概述 compaction主要包括两类:将内存中imutable 转储到磁盘上sst的过程称之为flush或者minor compaction:磁盘上的sst文件从低层向高层转储的过程称之为compa ...

  3. 64位系统目录在那里_教你玩转Linux系统目录结构

    Linux 内核最初只是由芬兰人林纳斯·托瓦兹(Linus Torvalds)在赫尔辛基大学上学时出于个人爱好而编写的.Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POS ...

  4. rocksdb原理_基于RocksDB实现精准的TTL过期淘汰机制

    本文来自OPPO互联网技术团队,如需要转载,请注明出处及作者. Parker 是 OPPO 互联网自研的一个基于 RocksDB 的分布式 KV 存储系统,它是一款类 Redis 的存储系统,主要解决 ...

  5. 手把手教你玩转SOCKET模型之重叠I/O篇(下)

    http://blog.csdn.net/PiggyXP/archive/2004/09/23/114908.aspx 四.     实现重叠模型的步骤 作了这么多的准备工作,费了这么多的笔墨,我们终 ...

  6. rocksdb原理_手摸手学习 RocksDB 的 Write Buffer Manager

    本文翻译自 RocksDB 官方 Wiki<Write Buffer Manager>: https://github.com/facebook/rocksdb/wiki/Write-Bu ...

  7. maya批量命名插件_教你玩转MAYA的四十二精华造诣(第一期)

    最近在整理文档时发现我收藏了一篇关于MAYA应用技巧的文章,突然有兴趣看了看,结果发现老版本MAYA中的某些内容很多已经无法应用于新版本.我又上网查了一下,结果发现网上好多帖子和我收藏的这篇内容基本一 ...

  8. python的精髓_教你玩转Python!一文总结Python入门到精髓的窍门

    (建议收藏) 很多人应该都有过这种经历,大量重复性工作:日报.周报.各种报,无穷无尽:不计其数的数据提取······琐碎繁杂的事务让工作的效率极低.如果可以一键完成就好了. 对这些问题来说,最高效的解 ...

  9. java游戏熊猫修牧场的_教你玩转牧场积分,角色练满25修不是梦想

    对于养号玩家来说,除了每天种种花以外,牧场系统大概是另外一个福音.每日只需花费5-10分钟打理,轻松易上手,牧场积分可以兑换大量储备金和修炼果等.下面让我们一起看看具体怎么操作吧.(牧场基础入门看多多 ...

最新文章

  1. “Linux频道”有链接打不开
  2. [置顶] ros的navigation之———gmapping应用详解(in ros)
  3. Java《剑指Offer》面试题2:替换空格
  4. php查找时间,PHP 查找并算出世界各地时间
  5. µVISION: Error: Encountered an improper argument
  6. 谷歌fuchsiaos和华为鸿蒙,华为鸿蒙最大的对手现身!谷歌正式推送Fuchsia OS,或替代安卓...
  7. Linux_linux常用工具------进度条程序
  8. xbmc addons
  9. C语言程序设计二期末考试,C语言程序设计期末考试试卷2.doc
  10. 看了2022华为春季发布会
  11. GridMask:SOTA 数据增广方法,显著改进分类、检测、分割效果
  12. Educational Codeforces Round 23 E. Choosing The Commander 字典树
  13. php钓鱼怎么使用方法,路亚钓法操作步骤及抛投技巧
  14. Yahoo! Screwdriver:可扩展的持续集成工具
  15. 影驰名人堂送的机器人_6999元纯白信仰!影驰GTX 1080 Ti HOF名人堂评测
  16. 临近空间大气环境特性
  17. 76 爬虫 - Scrapy案例(阳光热线问政平台)
  18. 热烈欢迎Ubuntu志愿者!
  19. linux shell 操作二进制文件(xxd、dd)
  20. arm cache ace chi

热门文章

  1. Html5结合JS实现浏览器全屏功能
  2. 元素加了position:absolute则该元素的text-align:center居中失效的解决办法
  3. TypeScript 交叉类型(intersection type)
  4. MS SQL 分页存储过程
  5. C# -- HttpWebRequest 和 HttpWebResponse 的使用
  6. 使用maven插件构建docker镜像
  7. setTimeout里如果有$(this),$(this)指的是谁?
  8. 上周热点回顾(7.8-7.14)
  9. python神经网络库 keras_在Python和R中使用Keras和Tensorflow进行深度学习
  10. 怎么把原来的墙拆掉_家装拆除不是简单的砸砸墙,它也是有技术的