💽

分散DBの構築 - TiDB / YugabyteDB -

2024/08/28に公開
1

背景

趣味で仮想通貨取引所のデータを集めたりしているのですが、その容量がそろそろ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 は説明によるとストレージエンジンの事で、つまりこの役割を与えられたノードにデータが蓄積されます。その他概要については、開発者の方が解説されている下記記事が非常に参考になります。

https://zenn.dev/koiping/articles/f4b6579f3e6a68

公式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 を編集します。パスワードでのログインを嫌うため、公開鍵認証の設定です。

/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
/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 ファイルを作成します。

~/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 などで次のファイルを作成します。

~/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

モニターで確認し、追加したノードのディスクに書き込まれている事を確認してください。

スケールインとスケールアウトの参考ページ。

https://docs.pingcap.com/tidb/stable/scale-tidb-using-tiup#scale-in-a-tidbpdtikv-cluster

[補足] TiFlash でのレプリカ作成

以下を参照してください。

https://docs.pingcap.com/ja/tidb/stable/create-tiflash-replicas#create-tiflash-replicas-for-tables

[補足]その他

自分の環境で試していて、次の点について判明したので補足しておきます。

  • 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 にも HOME/yugabyte/node/certs にそれぞれ対応する証明書を、HOME/var/generated_certs/10.0.0.X からコピーして、配布してください。

サービスの実行

それぞれのノードで次のコマンドを実行してください。

  • 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

tanukinettanukinet

追記: 2024/08/30

以下にあるスペックで動かしていましたが、PD, TiDB, TiKV が同一サーバ内にあると、8GB では足りませんでした。TiKV も、4GB では厳しい場面も多く

https://zenn.dev/tanukinet/articles/5512d7f7f8a9a6#vps環境

結局は以下のスペックで動かしています。TiFlash は、現状分析を行う事はないので、外しています。
※TiFlash はレプリケーションの設定をしないと動作しないのですが、デフォルトでメモリは確保してしまう挙動だったので、ノードとして外しました。

  • 10.0.0.1 -> PD, TiDB, TiKV (16GB)
  • 10.0.0.2 -> TiKV (8GB)
  • 10.0.0.3 -> TiKV (8GB)