Skip to content

Instantly share code, notes, and snippets.

@maiha
Last active August 24, 2021 15:44
Show Gist options
  • Save maiha/b30a3dd45a10b55d0896bee48bbeb5c2 to your computer and use it in GitHub Desktop.
Save maiha/b30a3dd45a10b55d0896bee48bbeb5c2 to your computer and use it in GitHub Desktop.
Galera vs. Group Replication

概要

これは何?

以下の情報を元に GaleraGR のレプリケーションの違いをまとめたもの。

レプリケーション方式

Galera Replication

  • active/activeのマルチmaster方式。3rd partyが考案。
  • mysql-5.5から利用可能。(実装: Codership, MariaDB, Percona)

Group Replication (GR)

  • active/activeのマルチmaster方式。(parimaryとread-onlyのグループ構成)
  • mysql-5.7から公式のプラグインとして利用可能。(正式リリースは5.7.17から)
  • 既存の実績ある技術をベースに作成。(GTID, Multi-Source Replication, Multi-threaded Slave Applier, Binary Logs)

共通点

(理論)

  • いずれも「The Database State Machine Approach (1999)」に基づいている。
  • データへの更新を「writeトランザクション」として表現する。(行単位のバイナリログを利用)
  • write set単位の処理によってレプリケーションを実現する。(write set replication = wsrep)

(構成)

  • active/activeのマルチmaster方式。
  • writeは複数のノードに対して行われ、全ノードが全データを持つ。
  • readは自分のノード(ローカル)に対してのみ発生する。
  • 外部のF/O機能が不要で、ノードの追加と削除が自動で可能。
  • データの一貫性を持つ。
  • 楽観的ロックを利用。(同時writeは最初のコミットが勝つ)

(制約)

  • InnoDB でのみ動く。(※恐らく、トランザクションが必須のため)
  • テーブル内のデータは主キーが必須。(※恐らく、行単位での変更として処理するため)
  • GTID が必須。
  • 1ノードに対してのみwriteするのが最も効率的。

用語

Galera

Group Replication

  • Group : クラスタのこと
  • Member : ノードのこと

クラスタ構成

Galera

  • Multi-Master
  • 全ノードが対等で、常に同じデータを持つ。(データ的なF/O処理が発生しない。slave遅延も存在しない)
  • どのノードに対してもread/writeができる。(とは言え、ノードを跨いだ排他ロックはデッドロックになる)
  • 台数を増やしても、データ冗長性が上がるだけでwrite性能はスケールはしない。(むしろwriteは遅くなる)

Group Replication

  • Multi-Master(primaryとread-onlyで構成)
  • デフォルトでは1ノードだけがprimaryに昇格する。
  • その他のノードは自動的に read-only になる。
  • primary はクラスタ内での自動投票で決まる。
  • primary にのみ書き込みができ、read-onlyノードに対してwriteした場合、以下のエラーが出る。
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement
  • 台数を増やしても、primary が1つのためwrite性能はスケールしない。
  • primaryを複数作ることはできるが、お互いを同期させる必要があるため結局writeはスケールしない。
  • また、複数primaryでは、スキーマ変更やデータ更新時の競合問題が発生する。(そのためデフォルトでsingle primaryモードが推奨されている)

write時の挙動

Galera

  1. クライアントが どこかのノード にwriteする
  2. 受け取ったノードは、その writeトランザクションを全ノードに配送する
  3. 全ノード から同意を得た後に、クライアントに成功を返す

Group Replication

  1. クライアントが primaryノード にwriteする
  2. 受け取ったノードは、その writeトランザクションを全ノードに配送する
  3. 大多数のノード から同意を得た後に、クライアントに成功を返す

write時の挙動(詳細)

Group Replication

障害時の挙動

例として、3ノードのクラスタで、1つのノードが以下のどちらかの状態になり、障害が発生したとする。

  • 落ちた
  • ネットワーク的に見えなくなった

Galera

  • writeの適用は一旦pendingされる(TODO: クライアントへの返答は?)
  • 「ノードが復活」or「ノードが切り離された(timeoutにて)」によってwriteが適用される

Group Replication

(masterが生存している場合)

  • 残り2ノードでwriteを受け付ける
  • 障害ノードがクラスタから切り離されなくても、自動的に2ノード体制で動きだす

(masterが見えなくなった場合)

  • 障害ノード(master)は少数派のため、writeの受け入れをやめる
  • 障害ノードがクラスタから切り離された後、残り2ノードの中で自動的に新masterを選出する(TODO: 切り離しは自動?)

データロスト

Galera

  • writeトランザクションは全ノードへの到達が保証されるため、可能性は極めて低い
  • Percona XtraDB Clusterの場合、凄く運が悪いとロストする(TODO: Percona以外では?)
    • 例: split brain発生→クラスタ再構築→新しいwriteを受ける→新クラスタが死ぬ

Group Replication

  • ack直後に、大多数ノード群が全滅した場合、そのwriteデータは少数ノードには未配送のためロストする

OS

Galera

  • FreeBSD, Linux
  • (Percona) Linuxのみ

Group Replication

  • Linux, Windows, Solaris, OSX, FreeBSD

制約

共通

  • InnoDBのみ
  • primary keyが必須

Galera

  • Percona XtraDB Cluster 5.7からは制約違反はテーブルの宣言時にエラーが出るようになった(それ以前は実行時エラー)
  • テーブルロックができない
  • write先は1箇所がよい。(複数ノードを跨いで排他ロックするとデッドロックする)

GTID

Galera

Group Replication

WAN Support

どちらも、「低レイテンシかつ高帯域」を前提にしている。

Galera

  • WAN利用可。

Group Replication

データ転送

用語

  • joiner : クラスタに参加しようとするノード
  • doner : joinerにデータを提供するノード

Galera

転送方式にはISTとSSTの2つがある。(Gcacheの大きさによって自動的に決定される)

  • IST: インクリメンタル転送(差分転送) # Incremental State Transfer
    • 短期間だけクラスタから離れていたノードの復旧に便利。(writeキャッシュがノードにある場合のみ可能)
  • SST: フル転送。 # State Snapshot Transfer
    • 新規ノード追加時に便利。自動でsnapshotを作成して全データを入れてくれる。  - donerの負荷が大きいため、参照を受けない(or 優先度おとす)ような対応をすることが望ましい。(TODO:自動復旧の場合の対策は?)

Group Replication

  • GTIDベースのバイナリログを利用。
  • 全ログがノードにない場合、新規ノードの追加には別途snapshot(初期データ)が必要。(TODO: コールドバックアップから復旧?)

バイナリログが不足している場合はこういうエラーが出る。

2017-01-16T23:01:40.517372Z 50 [ERROR] Slave I/O for channel 'group_replication_recovery': Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.', Error_code: 1236

データ転送(失敗時)

クラスタにあるノードをjoinさせる時、データ転送が失敗した場合のそのノードの挙動。

Galera

  • 最初の失敗で諦め、自身のmysqldを停止させる。

Group Replication

Auto Increment Settings

Galera

  • クラスタ台数に応じて自動で即座に調整される。(以下、3ノードの場合)
    • auto_increment_increment = 3
    • auto_increment_offset = 1~3(各ノードに依存)
  • wsrep_auto_increment_control でこの機能を無効にできる。(値を手動設定できる)

Group Replication

Multi-Threaded Slave Side Applying

Galera

  • 同じDBのテーブルで並列レプリケーションするスレッド数を指定できる。(version 5.5から対応)
  • wsrep_slave_threads で設定。(デフォルト: 1)
  • 行ロックの衝突は潜在的にありえるがマルチスレッドで実行される。

Group Replication

フロー制御

レプリケーションが遅いノードが出てきた時の挙動。

Galera

Group Replication

ネットワーク断絶(split brain)

クラスタ内のノード間でネットワーク疎通が取れなくなった場合の挙動。

Galera

(多数派のノード)

  • 新しいノードが接続してくるのを待つ。(TODO: その間はクライアントのリクエストをサーブする?blockする?)

(少数派のノード)

  • クラスタに復帰するまではread/writeともにサーブしない。(設定で変更可能)
  • ネットワーク復旧後は、データの同期とクラスタへの復帰が自動的に行われる。

Group Replication

(多数派のノード)

  • クライアントのリクエストをそのまま処理する。

(少数派のノード)

  • クライアントからのreadを受け付ける(dirty readが発生)
  • クライアントからのwriteを受け付ける(が、そのまま刺さる)
  • 切断後に再接続しても、自動的にクラスタへは復帰しない。

ノード間の通信プロトコル

Galera

  • Totem single-ring ordering and membership protocol を利用。
  • HAクラスタの通信層制御を行うフリーソフトである Corosync で利用されている通信プロトコル。
  • tokenリング型なのでノード数が増えるとオーバーヘッドが大きくなる。
  • ノード数が3→9に増えると、write性能が1/4に落ち込む。

Group Replication

モニタリング

Galera

  • status変数のみ利用。
  • ノード内からクラスタ情報を参照できない。(他のノード情報やそのステータスが分からない)
  • 但し、Perconaはperformance_schemaを利用している。(mysql-5.7から)

Group Replication

  • Performance Schema を利用。
  • このテーブルにクラスタ内の各ノードの情報が全て入っている。(ノードのメタ情報や状態)
  • 通常のテーブルとして参照できるので、外部アプリからノードの死活監視などにも利用できる。

スキーマ変更

スキーマ定義DDLを実行したときの挙動。

Galera

2種類の更新方法がある。cnfまたはクライアントの接続時設定によって選択できる。

  • Total Order Isolation (TOI) (デフォルト)  - 他のトランザクションを全てブロックし、全サーバで一貫性を持って更新する。  - 可用性一貫性
  • Rolling Schema Upgrade (RSU)  - 指定サーバをクラスタから切り離し更新する。レプリケーションは行われない。  - 可用性一貫性

RSUではノード間のデータおよびスキーマの一貫性が崩れ、クラスタ全体の可用性が損なわれる可能性があるため、TOIが推奨されている。

Group Replication

  • writeはブロックされない。(通常のInnoDBに同じ)

まとめ

機能         Galera   GR     (補足)
構成         Multi-Master Multi-Master GR:Primary-ReadOnly
台数         3~9台   3~9台  
OS           FreeBSD, Linux  色々 GR:Linux, Windows, Solaris, OSX, FreeBSD
WAN利用         ◯         ×                                
GTID           独自GTID  MySQL(5.6)                              
コンセンサス   TSO           XCOM     TSO = Totem Single-ring Ordering
write ack     全ノード    過半数                                
同期用データ   Gcache    binlog                                
write 識別 seqno GTID                              
write ノード数     1           1     Galera:デッドロックするので1    
readの可用性    高い         高い                                 
writeの可用性    低い         高い    Galera:1台落ちると刺さる      
readスケール     する     する
writeスケール   しない     しない   GR:将来的にグループを増やせる?
データロスト  極めて低い       低い  
slave遅延       なし         ?  
dirty read       なし         あり  
split brain抑制     ◯         △     GR: 少数派ではdirty readが発生
split brain復旧  ◯(自動)   ×(手動)   GR: 少数派は手動でクラスタに戻す必要がある
writeフロー制御  全台停止      速度緩和   GR: ノード別に速度を変更する
隔離レベル    設定可能    Read-Commited Galera: SERIALIZABLEは非推奨(同一ノードでのみ動く)
スキーマ変更   writeブロック ブロックなし Galera: TOIの場合             
write性能     遅(10~30%)  中(60~84%) 「非同期レプリケーション」との比較
repl性能        中           速い    
repl動作     ブラックボックス 驚き最小
同時write競合  楽観的ロック 楽観的ロック
F/O処理          不要       自動     GR: MySQL Routerも自動
ノード切り離し 自動(timeout)     ?    
ノード自動復旧    自動     ×(バグあり?)
ノード新規追加    自動repl    手動       GR: 無停止はかなり面倒        
自動リカバリ(差分)  ◯(IST)  △(binlogのみ)                            
自動リカバリ(全部)  ◯(SST)       ×                                   
LB              ×        ◯(Router) Galera: HAProxyなどが別途必要。Perconaはある
モニタリング      △           ◯       Galera: wsrep系のstatus参照のみ可能
多機能           豊富        中  
実績           数年間      なし  
安定性(現時点)    ◯          ×     GR: split brain周りの不具合が多い
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment