分散DBの構築 - TiDB / YugabyteDB -
背景
仮想通貨取引所のデータを集めているのですが、その容量がそろそろVPSストレージの限界に近づき、どうしようかと悩んでいます。クラウドに移行すればクラウド側で勝手にスケールしてくれるのでデータ容量を気にしなくて済みますが、いかんせん値段が高くなります。どうにか安く済ませる事ができないものかとネットを調べると、分散DBなるものがOSSで公開されている事を知りました。
これを自前で用意してやれば、より安く大規模なデータベースが運用でき、スケールも容易なはず。そう考え、タイトルにもある下記2つのサービスについて試してみました。
結論から言うと、YugabyteDB は私の期待した速度が出ず(もしかしたらチューニング次第でどうにかなるかもしれませんが…)、TiDBは満足のいく速度が達成できました。
今回はそんな両サービスをVPS環境に構築し検証したので、その手順についてまとめてみたいと思います。
VPS環境
下記スペックの3台のサーバー(OS: Ubuntu 20.04)をローカルネットワークに接続して使用します。今回私が構築したのは、下記ローカル環境への構築になります。
また、DBサーバーに対して私の期待したいスペックは以下です。
- 60 queries / 1s ※ほぼ書き込み
- 466 rows / 1s
- 31 KB / 1s
前述しましたが、上記スペックは、TiDBで叶いました(YugabyteDBではデータ容量の増加に伴い、途中からクエリが通らなくなりました)。そのため、TiDB ⇒ YugabyteDB の順で手順を記載します。
※ちなみにですが、私は元来の PostgreSQL ユーザーなので YugabyteDB を最初に試しました。今回は残念でしたが、更なる改善を期待しています。
TiDB
今回構築したサーバーの役割は以下としました。
- 10.0.0.1 -> PD, TiDB, TiFlash, TiKV
- 10.0.0.2 -> TiKV
- 10.0.0.3 -> TiKV
TiKV は説明によるとストレージエンジンの事で、つまりこの役割を与えられたノードにデータが蓄積されます。その他概要については、開発者の方が解説されている下記記事が非常に参考になります。
公式Docの手順はココです。手順が変わる可能性はありますが、2024/08/26 時点で私が構築した手順を記しておきます。
Install
本手順は 10.0.0.1 のみで行います。TiDBのとても賢いところは、各ノードには実行環境から自動でインストールしてくれるようにプログラムされている事です。本当に便利。
curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
source ~/.bashrc
tiup cluster
tiup update --self && tiup update cluster
SSH設定
あまり検証していませんが、公式Docでは各ノードの root ユーザーに SSH でログインできる事が前提条件のように書かれています。おそらくリモートでインストールする際にパーミッションを無視するための措置のように思いますが、詳細は未検証です。
10.0.0.1 の任意のローカルユーザーが、各ノードの root ユーザーにSSHで公開鍵認証するための秘密鍵を作成する手順を記載します。秘密鍵やポート番号のノード別の個別設定があるかは分かりませんが、今回の手順では、全ノードの root ユーザーの秘密鍵と SSH ポート番号は同一となります。
cd ~
ssh-keygen -t rsa -b 4096 # 秘密鍵と公開鍵の作成. デフォルトでは ~/.ssh/id_rsa と ~/.ssh/id_rsa.pub が作成される
sudo cp ~/.ssh/id_rsa.pub /root/.ssh/authorized_keys
sudo chown root:root /root/.ssh/authorized_keys
sudo chmod 400 /root/.ssh/authorized_keys
この /root/.ssh/authorized_keys を 10.0.0.2 と 10.0.0.3 に同一の内容をコピーします。
次に、10.0.0.1 ~ 3 の環境で次のように /etc/ssh/ sshd_config を編集します。パスワードでのログインを嫌うため、公開鍵認証の設定です。
Port 12345 # 任意のport番号
Protocol 2
PermitRootLogin yes
PasswordAuthentication no
ChallengeResponseAuthentication no
PermitEmptyPasswords no
MaxSessions 20
SSH のサービスを restart します。
sudo /etc/init.d/ssh restart
10.0.0.1 の端末で、次のコマンドでローカルユーザーから 10.0.0.2 と 10.0.0.3 の rootユーザーに SSH 接続できる事を確認してください。
ssh root@10.0.0.2 -p 12345 -i ~/.ssh/id_rsa # And 10.0.0.3
各サーバの環境設定
TiDB のノードに求められる環境を設定します。VPSの環境にも依存すると思いますし、感覚的に必要かなと思う箇所のみを設定しましたので、詳細は公式Docを参考にしてください。
- numactl のインストール
sudo apt update && sudo apt install -y numactl
必要そうな設定その1。
sudo bash -c "echo \"vm.swappiness = 0\" >> /etc/sysctl.conf"
sudo bash -c "echo \"fs.file-max = 1000000\" >> /etc/sysctl.conf"
sudo bash -c "echo \"net.core.somaxconn = 32768\" >> /etc/sysctl.conf"
sudo bash -c "echo \"net.ipv4.tcp_tw_recycle = 0\" >> /etc/sysctl.conf"
sudo bash -c "echo \"net.ipv4.tcp_syncookies = 0\" >> /etc/sysctl.conf"
sudo bash -c "echo \"vm.overcommit_memory = 1\" >> /etc/sysctl.conf"
sudo sysctl -p
必要そうな設定その2。再起動後も有効にするために /etc/rc.local
に書き込む。
sudo touch /etc/rc.local
sudo chmod 700 /etc/rc.local
sudo bash -c "echo \#\!/bin/bash >> /etc/rc.local"
sudo bash -c "echo \"swapoff -a\" >> /etc/rc.local"
sudo bash -c "echo \"echo never > /sys/kernel/mm/transparent_hugepage/enabled\" >> /etc/rc.local"
sudo bash -c "echo \"echo never > /sys/kernel/mm/transparent_hugepage/defrag\" >> /etc/rc.local"
sudo bash -c "echo \"echo none > /sys/block/vda/queue/scheduler\" >> /etc/rc.local"
sudo systemctl restart rc-local.service
tidb ユーザーに対するファイルディスクリプタ数の上限設定。
sudo bash -c "echo \"tidb soft nofile 1000000\" >> /etc/security/limits.conf"
sudo bash -c "echo \"tidb hard nofile 1000000\" >> /etc/security/limits.conf"
sudo bash -c "echo \"tidb soft stack 32768\" >> /etc/security/limits.conf"
sudo bash -c "echo \"tidb hard stack 32768\" >> /etc/security/limits.conf"
必要そうな設定その3。TiFlash サーバに適用します。
sudo vi /etc/fstab
-UUID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa / ext4 errors=remount-ro 0 1
+UUID=aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa / ext4 nodelalloc,noatime,errors=remount-ro 0 1
再起動します。
sudo reboot
TiDB クラスター設定ファイル作成
~/topo.yml
ファイルを作成します。
# # Global variables are applied to all deployments and used as the default value of
# # the deployments if a specific deployment value is missing.
global:
user: "tidb"
ssh_port: 12345 # 設定した port 番号に
deploy_dir: "/var/local/tidb-deploy" # 任意のディレクトリに変更
data_dir: "/var/local/tidb-data" # 任意のディレクトリに変更
# # Monitored variables are applied to all the machines.
monitored:
node_exporter_port: 9100
blackbox_exporter_port: 9115
server_configs:
tidb:
instance.tidb_slow_log_threshold: 300
tikv:
readpool.storage.use-unified-pool: false
readpool.coprocessor.use-unified-pool: true
pd:
replication.enable-placement-rules: true
replication.location-labels: ["host"]
tiflash:
logger.level: "info"
pd_servers:
- host: 10.0.0.1
tidb_servers:
- host: 10.0.0.1
tikv_servers:
- host: 10.0.0.1
port: 20160
status_port: 20180
config:
server.labels: { host: "host-main" }
- host: 10.0.0.2
port: 20161
status_port: 20181
config:
server.labels: { host: "host-1" }
- host: 10.0.0.3
port: 20162
status_port: 20182
config:
server.labels: { host: "host-2" }
tiflash_servers:
- host: 10.0.0.1
monitoring_servers:
- host: 10.0.0.1
grafana_servers:
- host: 10.0.0.1
クラスター起動と初期化
以下のコマンドで、各ノードに必要モジュールがインストールされます。コマンド実行後に表示されるパスワードは忘れないようにメモしてください。
tiup cluster deploy <cluster_name> v8.2.0 ~/topo.yml --user root -i ~/.ssh/id_rsa
クラスターを初期化します。
tiup cluster start <cluster_name> --init
[テスト]クライアント接続
MYSQLPASS="メモしたパスワード"
mysql -h 10.0.0.1 -P 4000 -u root --password=${MYSQLPASS}
# データベースを作成するコマンド
mysql -h 10.0.0.1 -P 4000 -u root --password=${MYSQLPASS} -e "CREATE DATABASE testdb;"
# SQLファイルを読み込んで実行するコマンド
mysql -h 10.0.0.1 -P 4000 -u root --password=${MYSQLPASS} --database=testdb < ~/test.sql
[テスト]クラスターの情報表示
tiup cluster display <cluster-name>
- Dashboard へのログインは root / "メモしたパスワード"
- Grafana へのログインは admin / admin
[補足]スケールアウト(ノードを追加する)
公式Docはココです。vi ~/scale-out.yml
などで次のファイルを作成します。
tikv_servers:
- host: 10.0.0.4
port: 20163
status_port: 20183
config:
server.labels: { host: "host-3" }
次のコマンドで追加ノードの環境をチェックします。
tiup cluster check <cluster-name> scale-out.yml --cluster --user root -i ~/.ssh/id_rsa
次のようになればOKだと思います。
Node Check Result Message
---- ----- ------ -------
10.0.0.4 cpu-cores Pass number of CPU cores / threads: 4
10.0.0.4 selinux Pass SELinux is disabled
10.0.0.4 timezone Pass time zone is the same as the first PD machine: Asia/Tokyo
10.0.0.4 cpu-governor Warn Unable to determine current CPU frequency governor policy
10.0.0.4 memory Pass memory size is 4096MB
10.0.0.4 thp Pass THP is disabled
10.0.0.4 service Pass service firewalld not found, ignore
10.0.0.4 command Pass numactl: policy: default
10.0.0.4 os-version Warn OS is Ubuntu 20.04.4 LTS 20.04.4 (ubuntu support is not fully tested, be careful)
tiup cluster check <cluster-name> scale-out.yml --cluster --apply --user root -i ~/.ssh/id_rsa
tiup cluster scale-out <cluster-name> scale-out.yml --user root -i ~/.ssh/id_rsa
以下が表示されれば成功です。
Scaled cluster <cluster-name> out successfully
設定をリロードしておきます。
tiup cluster reload <cluster-name> --skip-restart
モニターで確認し、追加したノードのディスクに書き込まれている事を確認してください。
スケールインとスケールアウトの参考ページ。
[補足] TiFlash でのレプリカ作成
以下を参照してください。
[補足]その他
自分の環境で試していて、次の点について判明したので補足しておきます。
- Trigger 関数はサポートしていない。参考
- テーブルパーティショニングはサポートしている
- デフォルトでは TiFlash は動作せず、オンライン分析処理用のレプリケーションはされない模様
YugabyteDB
私は普段から PostgreSQL を使用していたので、それと互換性がある YugabyteDB を始めに試してみましたが、データが蓄積されていくにつれてクエリが指数的に遅くなったので、私は運用を断念しました。
とりあえず、YugabyteDB の日本語記事が少なかったので、インストール方法などについてメモとして記載しておきます。
今回構築したサーバーの役割は以下としました。
- 10.0.0.1 -> leader
- 10.0.0.2 -> follower
- 10.0.0.3 -> follower
Install
Install といっても、module 一式をダウンロードしてローカルに展開するだけです。
wget https://downloads.yugabyte.com/releases/2.21.1.0/yugabyte-2.21.1.0-b271-linux-x86_64.tar.gz
tar xvfz yugabyte-2.21.1.0-b271-linux-x86_64.tar.gz && cd yugabyte-2.21.1.0/
コマンドを統一するため、リンクを貼っておきます。
ln -s ~/yugabyte-2.21.1.0 ~/yugabyte
Install 可能かのチェックを行います。
~/yugabyte/bin/post_install.sh
上記作業を 10.0.0.1 ~ 3 のサーバで行います。
証明書の作成
各ノードと通信するための証明書をそれぞれ発行します。10.0.0.1で作業します。
~/yugabyte/bin/yugabyted cert generate_server_certs --hostnames=10.0.0.1,10.0.0.2,10.0.0.3
まずは本作業を実行したノードに証明書を配布します。
mkdir -p $HOME/yugabyte/node/certs
cp $HOME/var/generated_certs/10.0.0.1/* $HOME/yugabyte/node/certs
同様に 10.0.0.2, 10.0.0.3 にも
サービスの実行
それぞれのノードで次のコマンドを実行してください。
- 10.0.0.1
~/yugabyte/bin/yugabyted start --secure --advertise_address=10.0.0.1 --base_dir=$HOME/yugabyte/node
- 10.0.0.2
~/yugabyte/bin/yugabyted start --secure --advertise_address=10.0.0.2 --join=10.0.0.1 --base_dir=$HOME/yugabyte/node
- 10.0.0.3
~/yugabyte/bin/yugabyted start --secure --advertise_address=10.0.0.3 --join=10.0.0.1 --base_dir=$HOME/yugabyte/node
Yugabyte ユーザーのパスワード変更
10.0.0.1 で次のように作業します。デフォルトのパスワードは次のファイルに格納されています。
cat ~/yugabyte/node/data/yugabyted_credentials.txt
パスワードを変更します。
~/yugabyte/bin/ysqlsh -h 10.0.0.1 -U yugabyte
\password
[補足]フォルダの削除
すべて削除する場合は次のコマンドをそれぞれのノードで実行します。
~/yugabyte/bin/yugabyted destroy
~/yugabyte/bin/yugabyted destroy --base_dir=${HOME}/var/node
~/yugabyte/bin/yugabyted destroy --base_dir=${HOME}/yugabyte/node
[補足]その他
自分の環境で試していて、次の点について判明したので補足しておきます。
- テーブルパーティショニングはサポートしている。
- デフォルトでレプリカが作成される。
~/yugabyte/bin/yugabyted start
の際に--fault_tolerance none
のオプションをつけてみたが、多分効いていなかった。
最後に
詳細な解説はできませんが省きますが、以上がインストール手順になります。TiDB の方はしばらく稼働させてみて、何か知見があれば共有します。
Discussion
追記: 2024/08/30
以下にあるスペックで動かしていましたが、PD, TiDB, TiKV が同一サーバ内にあると、8GB では足りませんでした。TiKV も、4GB では厳しい場面も多く
結局は以下のスペックで動かしています。TiFlash は、現状分析を行う事はないので、外しています。
※TiFlash はレプリケーションの設定をしないと動作しないのですが、デフォルトでメモリは確保してしまう挙動だったので、ノードとして外しました。