TiDBについてまとめてみた
近年、データベースの新しい区分として、NewSQLというものが登場し注目されているということで、その一つであるTiDBというデータベースについて調べてみました。
NewSQLとは、リレーショナルデータベースやNoSQLに続く新しいデータベースであり、HTAP(Hybrid Transactional/Analytical Processing)に向いたデータベースであるとのことです。
私自身、データベースの設計をする際に、トランザクション系の処理と分析系の処理でそれぞれ異なる設計をすることがありますが、本来やりたいこととしては、DBは分けたくない(データの置き場としてシンプルにしたい)と思い、メダリオンなどレイクハウス型のアーキテクチャなど良いなぁと思っていたところに、このNewSQLを見かけたので、調べてみようと思った次第です。
とりあえずReadMeを読んでみる
調べるにあたり、公式のサイトよりも少し踏み込んだ情報を知りたかったので、とりあえずReadMeを順番に読んでみることにしました。
TiDBのGitHubはこちら
※後で知ったのですが、TiDBの論文もあるとのことです。
こちらもいずれ読んでみたいですが、今回はGitHubのReadMeベースで調査を進めます。
TiDBの論文
What is TiDB?
TiDB (/’taɪdiːbi:/, "Ti" stands for Titanium) is an open-source distributed SQL database that supports Hybrid Transactional and Analytical Processing (HTAP) workloads. It is MySQL compatible and features horizontal scalability, strong consistency, and high availability.
- TiDBのTiは金属チタンから来ている(チタンは非常に強い金属であり、軽量かつ耐久性があるから)
- HTAPのワークロードに向いており、トランザクションと分析のどちらも行ける
- MySQLに互換性があり、水平方向のスケーラビリティと、強い一貫性、高可用性を兼ね備えている
上記を見た感じ、良いことづくめに見えます。
Key features(主な特徴)
- Easy horizontal scaling (水平スケールが容易)
The TiDB architecture design separates computing from storage, letting you scale out or scale in the computing or storage capacity online as needed. The scaling process is transparent to application operations and maintenance staff.
コンピューティングリソースとストレージノードが分離されているので、それぞれ必要に応じて水平スケール出来るよ、ということが書いてあります。後ほど出てきますが、アーキテクチャの概要図を見てみると、確かに計算処理用のノード(TiDBクラスター)とストレージのノード(Storageクラスター)が分離されているようです。スケーラビリティや耐障害性に優れていそうな感じです。
- Financial-grade high availability (金融レベルの高可用性)
Data is stored in multiple replicas, and the Multi-Raft protocol is used to obtain the transaction log. A transaction can only be committed when data has been successfully written into the majority of replicas. This guarantees strong consistency and availability when a minority of replicas go down. You can configure the geographic location and number of replicas as needed to meet different disaster tolerance levels.
以下の様なことが書いてあります。
- Raftプロトコル(分散合意プロトコル)を使っている → 詳しくないので改めて調査したいです
- 一定数のノードへのトランザクションログの書き込みが成功した際に、CommitをOKとする
- 一部のノードがクラッシュしても、分散保存しているのでデータはロストしない
- 地理的に分散配置することで、耐障害性と高可用性を実現することが出来る
以下の詳細なアーキ図は後ほどまた出てきますが、確かにデータの断片を別ロケーションのストレージノードに分散して保存することで、高い可用性が得られそうです。
- Real-time HTAP
TiDB provides two storage engines: TiKV, a row-based storage engine, and TiFlash, a columnar storage engine. TiFlash uses the Multi-Raft Learner protocol to replicate data from TiKV in real time, ensuring consistent data between the TiKV row-based storage engine and the TiFlash columnar storage engine. TiKV and TiFlash can be deployed on different machines as needed to solve the problem of HTAP resource isolation.
要約すると以下になります。
- TiKVとTiFlashという2種類のストレージエンジンを持っている
- TiKVは行指向で、TiFlashは列指向
- 行指向のTiKVはデータ追記に向いていて、OLTP向け
- 列指向のTiFlashはデータ分析クエリの処理に向いていて、OLAP向け
- TiKVのデータをTiFlashにリアルタイムで複製(Multi-Raft Learner protocol)
- TiKVとTiFlashの物理配置を分けることで、HTAPのリソースを上手く分離できる
- 地理的に分散配置することで、耐障害性と高可用性を実現することが出来る
OLTP用の行指向のTiKVと、OLAP用の列指向TiFlashという2種類のノードを組み合わせて、HTAPに対応しているとのことです。分散のアーキテクチャはAWSのAuroraなどのデータベースに似ていますが、個人的に2種類のエンジンに分けるという点について、なるほど!と思いました。使ってみたい。。
- Cloud-native distributed database
TiDB is a distributed database designed for the cloud, providing flexible scalability, reliability, and security on the cloud platform. Users can elastically scale TiDB to meet the requirements of their changing workloads. In TiDB, each piece of data has at least 3 replicas, which can be scheduled in different cloud availability zones to tolerate the outage of a whole data center. TiDB Operator helps manage TiDB on Kubernetes and automates tasks related to operating the TiDB cluster, making TiDB easier to deploy on any cloud that provides managed Kubernetes. TiDB Cloud, the fully-managed TiDB service, is the easiest, most economical, and most resilient way to unlock the full power of TiDB in the cloud, allowing you to deploy and run TiDB clusters with just a few clicks.
TiDBのクラウドでの利用について書かれています
- TiDBではデータごとに3つのレプリカを持っており、物理的に分散すれば広域障害にも耐えられる
- TiDB OperatorというKubernetes向けのTiDBクラスターの管理用ツールがある
- TiDB Cloudというマネージドサービスもあり、こちらが最も簡単に利用できる
TiDB Cloudが使える環境であれば、マネージドサービスなのでそちらを使うのが良さそうです。AWSについてはMarket Placeで公開されており、正式に連携が出来そうですが、Azureについては未だの様ですので、TiDB Operatorを利用して、AKS上で構築することになりそうです。
マネージドデータベースTiDB CloudがAWS Marketplaceに対応
Deploy TiDB on Azure AKS
- Compatible with the MySQL protocol and MySQL ecosystem
TiDB is compatible with the MySQL protocol, common features of MySQL, and the MySQL ecosystem. To migrate applications to TiDB, you do not need to change a single line of code in many cases, or only need to modify a small amount of code. In addition, TiDB provides a series of data migration tools to help easily migrate application data into TiDB.
TiDBとMySQLの互換性についてです。互換性は高そうです。
- MySQLと互換性がある。(プロトコルや基本的な機能、エコシステム)
- ほとんどの場合、MySQL用アプリケーションのコードをほぼ全く改修せずに移植できる。
- TiDB用のdata migration toolがあり、データ移行に使える
その他気になって調べたこと
Transaction Isolation Levels(トランザクション分離レベル)
TiDB implements Snapshot Isolation (SI) consistency, which it advertises as REPEATABLE-READ for compatibility with MySQL. This differs from the ANSI Repeatable Read isolation level and the MySQL Repeatable Read level.
TiDBでは実際はスナップショット分離レベルを採用しているが、MySQLとの互換性から、定義上はREPEATABLE-READとしている、とのことです。実態が Snapshot Isolation であれば、SERIALIZABLE相当だと思われるので、一貫性は充分なはず。ファントムリードも防止できる?(要検証)
TiDB Transaction Isolation Levels
TiDB Optimistic Transaction Model(楽観的ロックモード)
TiDBではロックモードとして楽観的モード(Optimistic)と悲観的(Pessimistic)モードが用意されており、デフォルトは悲観的ロックモードになるようです。
楽観的ロックモードの際のシーケンスは以下の通りとなります。
TiDB Optimistic Transaction Model
1.The client begins a transaction.
TiDB gets a timestamp (monotonically increasing in time and globally unique) from PD as the unique transaction ID of the current transaction, which is called start_ts. TiDB implements multi-version concurrency control, so start_ts also serves as the version of the database snapshot obtained by this transaction. This means that the transaction can only read the data from the database at start_ts.
- clientがTiDBにbeginリクエストを発行する
- TiDBはPDからトランザクションID(start_ts)を取得する
2.The client issues a read request.(読み込みリクエストの場合)
ⅰ.TiDB receives routing information (how data is distributed among TiKV nodes) from PD.
ⅱ.TiDB receives the data of the start_ts version from TiKV.
- ⅰ.TiDBはPDよりルーティング情報(どのTiKVノードにデータが分散されているか)を問い合わせる
- ⅱ.TiKVからstart_tsに応じたレコードを取得する
- クライアントに読み取ったレコードを返す
3.The client issues a write request.(書き込みリクエストの場合)
TiDB checks whether the written data satisfies constraints (to ensure the data types are correct, the NOT NULL constraint is met). Valid data is stored in the private memory of this transaction in TiDB.
- TiDBは書き込まれようとしているデータが制約を満たしているかを確認する(NOT NULLなど)
- 確認後、書き込みデータをTiDBのメモリ上に保存する
- クライアントに書き込みを受け付けた旨を応答する
4.The client issues a commit request.(Commit要求の発行)
5.TiDB begins 2PC, and persists data in store while guaranteeing the atomicity of transactions.(2相コミットにより、データを永続化)
ⅰ.TiDB selects a Primary Key from the data to be written.
- TiDBは書き込み対象のデータからPrimaryキーを抽出する
ⅱ.TiDB receives the information of Region distribution from PD, and groups all keys by Region accordingly.
- PDに問合せをして、各Primaryキー毎にどのロケーションにレコードを配置するかを決定する。
ⅲ.TiDB sends prewrite requests to all TiKV nodes involved. Then, TiKV checks whether there are conflict or expired versions. Valid data is locked.
- TiDBから各TiKVノードにprewriteのリクエストを発行する
- TiKVノードでは、トランザクションIDから更新の競合や期限切れが起きていないことを確認する
- バリデーションに合格した場合、対象のレコードをロックする(楽観的ロック)
ⅳ.TiDB receives all responses in the prewrite phase and the prewrite is successful.
- TiDBは全てのprewirteリクエストに対してresponseが得られたことを確認する
- 確認ができた場合、prewrite phaseが成功となる
ⅴ.TiDB receives a commit version number from PD and marks it as commit_ts.
- TiDBはPDからコミット時のトランザクションID(commit_ts)を取得する
ⅵ.TiDB initiates the second commit to the TiKV node where Primary Key is located. TiKV checks the data, and cleans the locks left in the prewrite phase.
- TiDBはPrimaryキーが配置されたTiKVノードに、2回目のcommit要求を発行する(2相コミット)
- TiDBはデータを確認し、prewrite phaseのロックを解除する
ⅶ.TiDB receives the message that reports the second phase is successfully finished.
- TiDBはデータを確認し、各TiKVノードから、2相コミットが完了を受信する
6.TiDB returns a message to inform the client that the transaction is successfully committed.(TiDBがコミットの完了をclientに通知)
7.TiDB asynchronously cleans the locks left in this transaction.(残ったロックを非同期で開放)
TiDB Pessimistic Transaction Mode(悲観的ロックモード)
悲観的ロックモードのシーケンスについても、基本的には楽観的ロックモードと同じになりますが、2相コミットの実行前にロックの取得が発生します。(楽観的ロックモードでは2相コミット処理の途中のprewirte phaseで取得)
TiDB Pessimistic Transaction Mode
1.(Same as the optimistic transaction mode) TiDB receives the begin request from the client, and the current timestamp is this transaction's start_ts.
- begin requestの後に、PDからstart_tsを取得(楽観的ロックモードと同じ)
2.When the TiDB server receives a writing request from the client, the TiDB server initiates a pessimistic lock request to the TiKV server, and the lock is persisted to the TiKV server.
- clientから書き込みリクエストを受信後、TiDBは各TiKVノードに対してロックを取得する(悲観的ロック)
3.(Same as the optimistic transaction mode) When the client sends the commit request, TiDB starts to perform the two-phase commit similar to the optimistic transaction mode.
- clientからcommit requestを受信後、2相コミットを実行(楽観的ロックモードと同じ)
なお、楽観的ロックのシーケンス図には明記されていませんでしたが、2相コミットの処理において、TiKVへのPrimaryキーの書き込みが完了した時点でcommitのsuccessを返しており、Secondaryキー以降につてはその後に遅延してcommitしているようです。
まとめ
- TiDBは2種類のエンジン(TiKVとTiFlash)を持つことで、OLTPとOLAPのどちらにも対応できる
- 3つのノードにレコードを複製するため、分散配置することで広域障害が起きても対応可能
- MySQLと高い互換性があり、既存のMySQL向けのコードをそのまま移植できるほど(場合による)
仕組み上、クラウド向けの分散DBという感じであり、ある程度以上の規模が無いと恩恵を受けられない可能性はありますが、HTAPを実現することが出来るDBであり、従来のRDBMS(MySQL)と同じ使用感で使えるということですので、今後ぜひ使ってみたいと思います。
Discussion