TiDBを触ってみて個人的に面白いと思ったものを雑にまとめます。
TiDBのことはある程度知っている人向けの話です。
- HTAP(TiFlash)
- リソース制御機能
- Stale Read
- Follower Read
- プッシュダウン
- レコードTTL
- コメント構文
- sync-diff-inspector
- ローカルPCでTiDBを起動する
- まとめ
HTAP(TiFlash)
TiDBといえば、HTAPが有名だと思う。
- https://docs.pingcap.com/ja/tidb/stable/explore-htap
- https://docs.pingcap.com/ja/tidbcloud/tiflash-overview
TiDBが苦手とするOLAPを高速に処理するために、 TiFlashという列指向NoSQLを外付けし、 OLAP系のクエリをそこに対して実行するという、 なんとも力技感がすごい機能である。
アーキテクチャ図は以下である。
TiDBに保存されたデータは自動的にTiFlashにコピーされる(保存される)ので、利用者がTiFlashの存在を意識する必要はない。 OLAP系のクエリを実行するときはTiDBが自動的にTiFlashに振り分けてくれる(クライアント側で指定することもできる)。 TiDBというNewSQLとTiFlashという列指向NoSQLを使いながらも、クエリがMySQL互換のもので済むのも地味に嬉しい。
ただ、TiFlashというノードが必要になるし、 データがコピーされるという仕様上、TiDBとTiFlashで同じデータを保存しないといけなくなるし、別に良いことばかりではない。
リソース制御機能
TiDBはマルチテナントを想定しているDBである。 マルチテナントというのは "マイクロサービス環境において各マイクロサービスのDBを1つのクラスターに乗せる" みたいなやつである。
しかし、マルチテナント型クラスターではノイジーネイバーのリスクがある。 特定のクライアントが重いクエリを実行し、クラスター全体に影響を与えてしまうアレである。
TiDBにはこれを予防する機能としてリソース制御機能がある。
これはその名の通り、クライアントが利用できるリソースを制御できる機能であり、 設定されたリソース以上を消費しようとするとクエリがエラーになる。
なんとなーく「5つのマイクロサービスがあったとして、CPU, Memoryを20%ずつ割り当てる」みたいな機能かなーと思ったが、 微妙に違った。 リソース制御機能の "リソース" の定義はリクエストユニット(RU)というもので、 以下のドキュメントを読んでもらえると分かるが、まあまあ複雑である。
実際にTiDBを利用してみて、 RUの実績値を確認し、 それを参考に設定していく感じかなーと思っている。
Stale Read
Stale Readは過去のデータを読み取る機能である。 例えば「5sec前のデータを取得する」みたいなことができる。
最新のデータを読み取るわけではないので、 リーダーではないレプリカ(フォロワー)からもデータ取得が可能になり、 レプリカ間の負荷分散が可能になる。
ただ、クラスター全体で処理するクエリ数は変わらないので、 あくまで "リーダーのレプリカに負荷が集中してやばい" みたいなケースで活躍する機能だと思う。
Follower Read
Follower Readは最新のデータを読み取りつつも、 リーダーではないレプリカ(フォロワー)からデータを取得できる機能である。
上記で説明したStale Readもフォロワーからデータを取得できる機能なので混乱しそうになるが、 Stale Readは過去のデータをフォロワーから取得する機能で、 Follower Readは最新のデータをフォロワーから取得する機能である。 フォロワーが最新のデータを持っていない場合は、最新のデータが反映されるまで待つことになる。
そして、Follower Readには "同一ゾーンにあるレプリカからデータを取得する" という機能もある。
どーゆーことかというと・・・AWSやGoogle Cloudでインフラを構築する場合、 複数のゾーンにインスタンスを配置することで耐障害性を向上させることができるが、 TiDBも分散システムなので同じような形でノードを配置することになる。 ただ、ノード間の通信がゾーンをまたぐと転送費用がかかったり、レイテンシが高くなってしまう。
Follower Readは通信が同一ゾーン内に閉じるようにクエリをレプリカにルーティングしてくれるので、 転送費用とレイテンシを削減することができる。 k8sの "Topology Aware Hints" みたいなものだと思う(多分)。
プッシュダウン
TiDBには "Predicate Push Down(PPD)" というデータのフィルタリング処理を高速に処理するための機能がある。
TiDBはシステムアーキテクチャ上、TiDB clusterとStorage Clusterに分かれており、 実際にデータが保存されるのはTiKVというノードである。
TiDB cluster はTiKVからデータを取得するときに、 Storage Cluster側でデータのフィルタリングを処理しようとする。 これがプッシュダウンである。
例えば以下のようなシンプルなフィルタリング条件のクエリがあった場合、
select * from t where a < 1;
TiDB Cluster はStorage Cluster側に "where a < 1" のフィルタリングを依頼し、フィルタリングされた結果のみを返してもらって、それらを結合してクライアントに返す。 言われてみると当たり前の機能(フィルタリング方法)かもしれない。
しかし、以下のクエリはプッシュダウンが効かない。
select * from t where truncate(a, " ") = '1';
なぜかというと、Storage ClusterであるTiKVが "truncate()" をサポートしていないからである。
TiDBはMySQLプロトコル互換なので、truncate() をサポートしているが、TiKVがサポートしているわけではないので、 上記のクエリはプッシュダウンが効かないらしい。
MySQLプロトコル互換なのでクエリ自体は動くが、 パフォーマンス良い状態で実行できるかどうかは別問題なので、 場合によってはチューニングが必要になるケースがある。
レコードTTL
TiDBはレコードに有効期限を持たせることができる(有効期限が切れるとレコードは自動的に削除される)。
RedisやDynamoDBにあるアレである。
設定方法は以下のようにテーブル定義で指定するだけ。
CREATE TABLE t1 ( id int PRIMARY KEY, created_at TIMESTAMP ) TTL = `created_at` + INTERVAL 3 MONTH;
この機能がどうやって実現されているかというと、 TiDBが裏側で定期的に有効期限が切れているレコードをSELECTして、DELETEしている。 なんとなく力技感がすごい。 レコードの消し込みバッチみたいですね。
レコードの削除はデフォルト設定だと1時間間隔で定期的に実行されるのでリアルタイム性はないことに注意。 SELECT, DELETEの実行量によってはクラスターに影響を与えてしまうと思うかもしれないが、可能な限り影響を与えないようになっているらしい。
個人的に一番便利だと感じる機能である。
コメント構文
TiDBはMySQLプロトコル互換なので、MySQLのクエリやエコシステムがそのまま使えるのが強みである。
しかし、TiDB特有の機能を設定する場合は、それを満たせなくなることがある。 例えば以下のレコードTTLを設定したテーブル定義がそれにあたる(TTL設定の構文がMySQL互換ではない)。
CREATE TABLE t1 ( id int PRIMARY KEY, created_at TIMESTAMP ) TTL = `created_at` + INTERVAL 3 MONTH;
上記のテーブル定義に対してMySQLのエコシステムに利用すると、構文として間違っているので、上手く動かない可能性が高い。
しかし、TiDBにはコメント構文でTiDB特有の設定を可能にする仕組みがある。 先程のテーブル定義は以下のように書くことができる。
CREATE TABLE t1 ( id int PRIMARY KEY, created_at TIMESTAMP ) /*T![ttl] TTL = `created_at` + INTERVAL 3 MONTH TTL_ENABLE = 'OFF'*/;
TTLの定義はMySQLではコメントとして認識され、TiDBではTTLの設定として認識される。 MySQL互換なテーブル定義になるので、既存のエコシステムを利用し続けることが可能である。
sync-diff-inspector
sync-diff-inspectorはTiDB用のデータ比較ツールである。 MySQLからTiDBへのDB移行時に利用される。
このツールを簡単に説明すると、 "MySQL, TiDB間のデータ差分を検出し、その差分を埋めるためのSQLを出力してくれるツール" である。
sync-diff-inspectorを日時実行し、差分解消SQLが出力されたら、それを自動的にTiDBに実行することで、 日時でデータの同期を取る仕組みを構築することができる。 とっても便利。
ローカルPCでTiDBを起動する
TiDBはOSSなのでローカルPCで起動できる。 ローカルPCでの開発作業やCIでのテスト実行に使うには十分である。
まとめ
TiDBはNewSQL/分散DBとしての複雑さを持ちますが、そこが魅力であり、面白いなーと思います。