TiDB User Day 2024のアーカイブ動画を公開中!詳細を見る

この記事では、2017年8月28日に開催されたRocksDBミートアップでSiddon Tangが行った講演の内容を紹介します。

講演者の紹介

RocksDBチームのみなさんこんにちは。本日はお招きいただきありがとうございます。

これから、TiKVRocksDBをどのように利用しているのか説明していきたいと思います。本題に入る前に、簡単な自己紹介をします。PingCAPのチーフエンジニアを務めているSiddon Tangと申します。現在、次世代SQLデータベースであるTiDBと、キーと値の分散型トランザクションストアであるTiKVの開発に携わっています。私はオープンソースを強く支持しており、LedisDB(バックエンドエンジンもRocksDB)、go-mysql、go-mysql-elasticsearchなどのオープンソースプロジェクトを推進してきました。

アジェンダ

本日は、以下の事項を説明します。

  • なぜRocksDBを選択したのか
  • TiKVではどのようにRocksDBを利用しているのか
  • RocksDBに対し、どのような貢献をしているのか
  • 今後のプラン

なぜRocksDBを選択したのか

それでは始めましょう。当社は、LevelDBやWiredTiger等のエンジンではなく、RocksDBを利用することに決めました。それはなぜでしょうか。多くの理由があります。

  • 第一に、RocksDBは高速です。単一のインスタンスに大量のデータがあっても、書き込み/読み取りのスピードを維持できます。
  • そして言うまでもなく、RocksDBは安定しています。RocksDBチームは、安定性を保証するために多くのストレステストを行ってきました。
  • また、組み込みが容易です。TiKVはRustで記述されているので、FFIを介し、RocksDBのC APIをRustで直接呼び出すことができます。
  • 多くの役立つ機能を備えているほか、実稼働環境でそれらの機能を直接利用し、パフォーマンスを改善することができます。
  • さらに、RocksDBは今でも速いペースで開発が進んでいます。多くの素晴らしい機能が追加され、パフォーマンスが改善し続けています。
  • その上、RocksDBのコミュニティは非常に活発です。何かわからないことがあったら、気軽に相談することができます。多くのRocksDBチームメンバーと私たちは、WeChat(中国で広く普及しているIMツール)フレンドでもありますので、お互いに直接会話することができます。

RocksDBをどのように利用しているのか

TiKVのアーキテクチャ

RocksDBを利用することを決断した後、次の問題となるのは、TiKVでRocksDBをどのように利用するかということです。TiKVアーキテクチャの簡単な説明から始めましょう。

第一に、TiKVノードのデータはすべて、2つのRocksDBインスタンスを共有しています。1つはデータ用、もう1つはRaftログ用です。

リージョン

リージョンとは、ある範囲のデータを対象とした、論理的概念です。各リージョンは複数のマシンに常駐しており、多数の複製を持っています。これらすべての複製が1つのRaftグループを形成します。

Region

Raft

TiKVはRaftコンセンサスアルゴリズムを使用してデータを複製します。したがって、書き込みリクエストがある度に、私たちはまずRaftログにリクエストを書き込み、ログがコミットされた後、Raftログを適用してデータを書き込みます。

Raft

RocksDBに保存されるRaftログのキーフォーマットは、リージョンIDにログIDを付けたものになります。ログIDは単調に増加していきます。

InsertWithHint

InsertWithHint

新しいRaftログはすべて、リージョンに追加します。例えば、まずリージョン1にログ1を追加し、その後同一のリージョンにログ2を追加します。ヒント機能を持ったMemtable挿入を利用します。この機能によって、挿入パフォーマンスは15パーセント以上向上します。

Key and Version

該当するバージョンはサフィックスとしてキー内に組み込まれ、ACIDトランザクションに対応するために利用されます。しかし、トランザクション管理については、今回のトピックから外れるので、説明は省略します。

プレフィックスイテレーター

Prefix Iterator

ご存知のとおり、私たちはタイムスタンプサフィックスを付けてキーを保存します。ところが、タイムスタンプがないキーしかシークできないので、プレフィックス抽出機能を設定し、Memtableブルームフィルタを有効化します。これにより、読み取りパフォーマンスを10パーセント以上改善することができます。

リージョン分割チェックのためのテーブルプロパティ

Table Property for Region Split Check

多くのデータをリージョンに挿入していると、データサイズは所定のしきい値をすぐに超えてしまいます。すると、リージョンの分割が必要になります。

以前の実装では、まずリージョンの範囲内のデータをスキャンし、次いでデータの合計サイズを計算し、合計サイズがしきい値を超えていれば、そのリージョンを分割していました。

リージョンのスキャンにはI/Oコストが多くかかっていました。しかし、現在は代わりにテーブルプロパティを利用します。圧縮を行う際にデータ合計サイズをSSTテーブルプロパティに記録します。範囲内のすべてのテーブルプロパティを取得し、その後、合計サイズを合算します。

最終的に合算されたデータサイズは概算となりますが、この方法は効率がよく、無意味なスキャンを回避できるので、I/Oコストが削減されます。

GCチェックのためのテーブルプロパティ

Table Property for GC Check

キーについては、私たちは複数のバージョンを利用しており、古くなったキーは定期的に削除します。しかし、ある範囲においてGCを実行する必要があるかどうかわかりません。この場合、以前はすべてのデータをスキャンするしかありませんでした。

ところが、GCを実行する必要があるのは所定のセーフポイントの前だけであり、ほとんどのキーには1つのバージョンしかないため、これらのキーを毎回スキャンするのは非効率です。

そこで、MVCCプロパティコレクターを作成し、バージョン情報を収集します。このバージョン情報には、最大・最小タイムスタンプ、行番号、バージョン番号などが含まれています。すると、範囲をスキャンする前に毎回、これらのプロパティをチェックし、GC手順をスキップできるかどうかを確認することができます。

例えば、テーブルプロパティの最小タイムスタンプがセーフポイントよりも大きいことがわかれば、その範囲のスキャンを即座にスキップすることができます。

SSTファイルの取り込み

Ingest the SST File

以前の実装の場合、一括読み込みを行うときは、該当する範囲内のすべてのキーと値をスキャンし、ファイルに保存する必要がありました。その後、別のRocksDBで、ファイルからすべてのキーと値を読み取り、それらをバッチで挿入していました。

ご存知のとおり、このフローは非常に遅く、RocksDBには高い負荷がかかる可能性があります。そこで現在は、代わりにIngestFile機能を利用します。最初にキーと値をスキャンし、それらをSSTファイルに保存します。その後、SSTファイルを直接取り込みます。

その他

Others

上記以外にも、サブ圧縮やパイプライン方式の書き込みを実現しているほか、ダイレクトI/Oを利用して圧縮やフラッシュを行っています。これらの素晴らしい機能のおかげで、パフォーマンスを改善することができます。

どのような貢献をしているのか

私たちは、RocksDBを利用しているだけではなく、コミュニティに貢献できるよう最善の努力をしています。多くのストレステストを行い、重大なデータ破損バグをいくつか発見しました。一部の例を挙げます。

  • #1339: 同期書き込み + WALは、依然として最新データを喪失させる場合がある。
  • #2722: 削除済みのキーの一部が、圧縮後に表示される場合がある。
  • #2743: 範囲削除とMemtableプレフィックスブルームフィルタのバグ。

幸いにも、ユーザーの実稼働環境でこれらの問題が発生したとの報告はありません。

また、機能を追加したり、いくつかのバグを修正したりしました。TiKVで呼び出せるのはRocksDB C APIのみなので、私たちは欠落しているC APIをRocksDB向けに多く追加しています。

  • #2170: WriteBatchのPopSavePointをサポート。
  • #2463: nullptrをリリースする際のcoredumpを修正。
  • #2552: CMake、対応できる圧縮タイプを追加。
  • さまざまなC API

今後のプラン

今後、DeleteRange APIを開発する予定ですが、これは非常に便利なAPIです。ただ現在のところ、27522833のバグが見つかっており、これを修正するために最大限努力しています。もちろん、RocksDBチームとも協力しています。

また、BLOB DBの安定性が確認されたら、これを試用する予定です。一方、挿入パフォーマンスを向上させるため、さまざまなMemtableタイプを試してみる予定です。また、SATAディスク向けにパーティションインデックスやパーティションフィルタを利用していきます。


Have questions? Let us know how we can help.

Contact Us

TiDB Cloud Dedicated

TiDB Cloudのエンタープライズ版。
専用VPC上に構築された専有DBaaSでAWSとGoogle Cloudで利用可能。

TiDB Cloud Serverless

TiDB Cloudのライト版。
TiDBの機能をフルマネージド環境で使用でき無料かつお客様の裁量で利用開始。