MySQL Semi-Synchronous Replication in Facebook

MySQL standard Semi-Synchronous Replication

  • MySQL 5.5から導入された機能で、コミット時にマスタのバイナリログとスレーブの中の1台のリレーログとの同期を取ってから、クライアントに応答を返す(これをNormal Semi-Synchronous Replicationと呼ぼう)

    • スレーブと同期するオーバーヘッドは増えることになるが、コミット毎にマスタ側でバイナリログとInnoDBログファイルをディスクにsyncする必要はなくなる*2
    • つまりこれは、Semi-Syncによるマスター・スレーブ間のRTTを増やし、マスターのsync(fsync())によるIOPSを減らす、ということ
    • RTTを抑えるため、Semi-Syncのスレーブは、マスタと同じデータセンターに置くべき
    • リレーログが最新となっているスレーブに全てのトランザクションが同期されているため、復旧時にマスタのバイナリログを参照する必要はない
    • スレーブはリレーログを非同期に適用するので、"Semi"-Synchronousと呼ばれる*3
  • MySQL 5.7から導入されたLoss-Less Semi-Synchronous Replicationでは、コミット時にスレーブと同期が取れるまで、ストレージエンジンへのコミット処理は行わない

    • Normal Semi-Sync では、スレーブと同期を取りにいっている間に(スレーブからACKが返る前に)ストレージエンジンへのコミット処理を行ってしまう
    • そのため、他のトランザクションに更新後のデータが見えてしまうが、該当のデータはスレーブに届いていない可能性がある
    • 届いていない場合、スレーブのリレーログを用いて復旧しても、該当のデータは存在しない
    • クライアントに応答は返していないので、該当のデータは正しく更新されていないことになりデータの欠損にはならないが、他のトランザクションに見えてしまったデータが消えてしまうのでPhantom Readと言われる
  • MySQL Replication: Loss-less Semi-Synchronous Replication on MySQL 5.7.2

Fast failover looses data without SemiSync

  • マスタの再起動無しに、スレーブをマスタに昇格させる
  • 数秒から数十秒でマスタの復旧が可能
  • マスタの障害検知とスレーブのマスタへの昇格を自動的に行う「完全自動化」と、スレーブのマスタへの昇格を一つのコマンドで実行する「半自動化」に分かれる
  • スレーブを完全にマスタと同期してマスタに昇格させるには、マスタのバイナリログが必要になるが、SemiSyncが無効の場合のFast failoverではマスタの完全なバイナリログを参照できないため、データの欠損が発生する

Facebook uses mysqlbinlog for SemiSync

  • MySQL 5.6で導入された --raw と --read-from-remote-server オプションにより、リモートからバイナリログのバックアップを取ることが可能
  • Facebookでは、mysqlbinlogをSemiSyncプロトコルが話せるように拡張
  • スレーブを立てる代わりにこの拡張版mysqlbinlog用いてSemi-Syncを実現している
  • 参照クエリ用のスレーブでなければ、MySQLサーバを立てるのはオーバーヘッドが大きいため

SemiSync breaks with a lot of non-SemiSync readers

  • 5.6.17より前はplugin_lockのmutex contentionバグがある
  • 5.7をバックポートしても、SemiSyncでないスレーブが多い場合に性能が落ちる

*1:Facebook(ex. DeNA)のMHA/HandlerSocketのコミッタ

*2:sync_binlog!=1とinnodb_flush_log_at_trx_commit!=1で運用できる

*3:全てのスレーブと同期を取らないから、という意味も?