レプリケーションのゆるーいお話 その1
記念すべき1回目の内容はMySQLらしく(?)レプリケーションの話を浅いところでしようと思います。
みんな好きですよね?レプリケーション。
僕は大好きです。
今回はレプリケーションってどんなものなのか、どういったメリット・デメリットがあるのかについて書きます。 初回なので込み入った話は一切しません。
レプリケーションとは
レプリケーション(Replication)とは、Replicaという言葉からもわかるようにデータベースを複製する技術です。
MySQLといえばレプリケーション、レプリケーションといえばMySQLと言われるぐらいMySQLにおいてレプリケーションは基本的な技術です。(個人の感想です)
レプリケーションにおいてベースとなるサーバをMaster、その複製となるものをSlaveもしくはReplicaと呼びます。
レプリケーションの原理を至極単純に表現すると 「同じ箱に同じものを同じ順番で入れていけば最終的にどちらも同じ状態になる」というものです。
考え方としてはとても単純ですよね?
MySQLではレプリケーションを構成するのが比較的簡単です。さらにMySQL 8.0.17で追加されたCloneプラグインというものを使うことでより簡単にレプリケーション構成を組むことが容易になりました。
参考
MySQL :: MySQL 8.0 Reference Manual :: 5.6.7 The Clone Plugin
レプリケーションのメリット
レプリケーションのメリットをいくつかピックアップしてみましょう。
- データの冗長化
- 可用性の向上
- 参照負荷分散
- バックアップサーバとしての利用
- MSRを利用したMaster統合
データの冗長化・可用性の向上
レプリケーションのメリットとしてすぐに思いつくのがこのデータの冗長化ではないでしょうか。 MasterとSlaveは常に同じデータを持っているはずなので、(もちろん状況によってはその場限りではないです)どちらか一方のサーバがダウンしてしまったとしてもデータが完全に消失してしまうといったことを防ぐことができます。
同じような理由で可用性の向上も望めます。 例えばMasterサーバがダウンしてしまった場合でもSlaveをMasterとして使うこと(これをMasterに昇格させるなどと言います)でサービスの停止時間を短くすることができます。
Master昇格を自動で行ういわゆるHAソリューションなどをうまく利用すればさらにサービスを安定させることができるでしょう。
最近ではInnoDB Clusterと呼ばれるMySQL NativeのHAソリューションも存在します。
参考
MySQL :: MySQL 8.0 Reference Manual :: 21 InnoDB Cluster
参照負荷分散
Slaveを複数台用意することで参照負荷を分散させることができます。 例えば複数台のSlaveをL4スイッチにぶら下げるなどすればアプリケーション側でSlaveの台数を意識することなく参照負荷を分散させることできます。
じゃあ更新負荷は分散できないの?と思われるかもしれませんが、NDB Clusterというものがありこちらを使うと更新負荷を分散できるようですが結構クセがあるようです。
参考
MySQL :: MySQL 8.0 Reference Manual :: 22 MySQL NDB Cluster 8.0
バックアップサーバとしての利用
Slaveをバックアップサーバとして利用することもできます。
DBにおいてバックアップを取ることはとても重要です。 しかしアクティブユーザーが多く常に負荷が高いといったサービスだとバックアップを取ることが難しいことがあります。 このような場合ではもう1台Slaveを増やしバックアップを取るためのバックアップ専用サーバとして用意するといいでしょう。
MSRを利用したMaster統合
MSRとはMulti Source Replicationの略で簡単に言うと1台のSlaveに対して複数のMasterが存在するレプリケーショントポロジーです。 MSRを使うと例えば垂直分散しているデータベースをSlaveで統合し、集計データなどを取ることが可能です。
この機能はMySQL 5.7とそれ以降のバージョンで利用できます。 逆に言うとそれ以前のバージョンではSlaveは1台のMasterしか持つことできませんので注意です。(Masterは複数のSlaveを持つことが可能です。)
レプリケーションのデメリット・注意点
上記のように便利なレプリケーションですが、もちろんデメリットや注意点もあります。
レプリケーション遅延
SlaveがMasterから(極端に)遅れている状態をレプリケーションが遅延しているなどと表現します。 簡単な例を挙げてみましょう。
とあるゲームでAくんがitem_1を10個購入したとします。 このときDBに例えば次のようなリクエストが送られたとしましょう。
UPDATE items SET item_cnt = item_cnt + 10 WHERE userId = 'userA' AND itemId = 'item_1';
カラム名など細かいことは今はどうでもいいのですが、ここではAくんがitem_1を10個購入して、それをDBに反映させたと思ってください。 もちろんこのクエリは問題なくMaster側で処理され、クライアントには購入に成功した旨のメッセージが返されるでしょう。
ところがSlaveが遅れているのでMasterの変更がSlaveに反映されるまでタイムラグがあります。
この状態でSlaveのitems
テーブルを参照してしまうとアイテムを購入する前のデータが見えてしまいます。
Master1台だけであればレプリケーション遅延を意識する必要はありませんが、レプリケーションを構築する場合はこの問題についても常に考慮すべきでしょう。
MySQLのレプリケーションでは原則完全同期はされません。 そのためリアルタイム性が問われるようなリクエストはMasterに投げるべきでしょう。
管理・監視の複雑化
ざっくりまとめてしまいましたが、サーバが増えるということは管理・監視すべき項目が増えるということです。 また上述した通りSlaveがMasterから極端に遅れてしまうといけません。(もちろんそのサーバがホットスタンバイサーバであれば話は別ですが) 監視するときはそのあたりもしっかりチェックしておいたほうがいいでしょう。
レプリケーションは単純なバックアップとはならない
これはたまにリアルでも勘違いされている方がいらっしゃるのですが、レプリケーションだけではバックアップは実現できません。
どういうことかというとレプリケーションだけでは誤ってデータ削除、テーブルの削除をしたときにデータを復旧させることができないからです。(RAIDはバックアップにはならないと同じ意味ですね)
これを防ぐには定期的にバックアップを取っておくことが大切です。もちろんサービス当初からの変更ログをすべて保存しておけば原理的には復旧は可能ですがやりたくはないですよね?(少なくとも僕はやりたくないです)
今回のトピックからはずれますが、バックアップはちゃんとリストアできることを確認しましょう。リストアできないバックアップとか冗談でも笑えませんので。
まとめ
今回はレプリケーションについてとても簡単にまとめました。
とりあえずこんなことができるんだーと思っていただければ幸いです。