MySQL5.7のマルチソースレプリケーション

今日、私の話は、いくつかのソースからのMySQLでのデータベース複製のようなエキサイティングなことについてです。 この記事は「究極の真実」のふりをするものではなく、私の問題との関連でこの技術の特徴を強調することを目的としています。 それでは始めましょう。 昔々、遠い銀河...



冒険は突然始まりますが、今回も起こりました。 私が開発しているアプリケーションの詳細は、さまざまなオフィスのさまざまなユーザーがデータベースに記入するだけでなく、他の部門の同僚のデータを表示する必要があるということです。 古典的なクライアント/サーバーアーキテクチャのように見えますが、...ある夜、上司がオフィスに来て、プロジェクトに関するニュースを発表しました。「アプリケーションは複数のオフィスで動作するはずです。セントラルオフィスから切断された場合、ユーザーが保存したデータの損失は許容できません それについて考えてください。」という言葉が言われています-解決策を探しましょう。 開発者とオフィス管理者との間の問題のあらゆる側面についてしばらく議論した後、「レプリケーションは私たちを助けます!」という判定が出されました。非常に安定しています。 ええ、そうです、私たちは急いでいるわけではありません。リリース時に落ち着くかもしれません。



MySQLでのレプリケーションの原則に慣れていない場合は、このトピックを読むことをお勧めします。 データレプリケーションMySQLマスタースレーブレプリケーションの設定方法



私の観点から、何かを学ぶ最も簡単な方法は練習することです。 始めましょう。 最初に、複製する必要があるものとその方法を決定します。 次のアーキテクチャを選択しました。 各企業のオフィスには、このオフィスからのデータのみを保存する独自の中間MySQL Masterサーバーがあります。 エンドユーザーからのINSERT、UPDATE、DELETEリクエストを収集します。 ユーザーは、すべてのSELECTクエリを中央の物理的にリモートのスレーブサーバーに送信します。 中央サーバーへの接続がない場合、SELECTクエリはオフィスの中間マスターサーバーに送信されます。 これは、MySQL自体のレプリケーション機能によるものです。 実際、複数のソースからのレプリケーションは、スレーブサーバー上でデータが同期される複数のマスターサーバーが存在するマスタースレーブスキームに従って行われます。 その結果、スレーブサーバー上のデータを変更すると、レプリケーションエラーが発生します。 さらに、私の場合、オフィスのユーザーからのデータの保存は、サンプルのデータの関連性よりも重要です。 その結果、一般的な作業スキームはそのようになり、ユーザーはデータを中間サーバーに保存し、そこから中央サーバーに移動し、ユーザーが選択のリクエストを送信すると、中央サーバー(使用可能な場合)に送信され、そうでなければ中間サーバーに送信されます。

出来上がり、そして羊は安全で、狼はいっぱいです。 ユーザーは、中央サーバーの可用性を考慮することなくデータを保存できます。中央サーバーは、ユーザーとの接続が復元されるとすぐに中間サーバーからすべてのデータを受信します。



私の場合、中間サーバーと中央サーバーの両方のデータベース構造はまったく同じです。つまり、キーフィールドの一意性という問題があります。 アプリケーションレベルで独自に独自性を監視する必要があります。そのため、このレコードが属する中間サーバーの番号が書き込まれる特別なフィールドを各データベーステーブルに追加することにしました。



Id | company_id | field1 | field2 1 | 1 | somevalue1 | somevalue1 2 | 1 | somevalue2 | somevalue2
      
      





さらに、中央サーバー上のデータベースのテーブルの構造をわずかに変更して、Idフィールドが一意ではないようにする必要があります。その結果、中央サーバーのテーブルデータは次の構造になります。



  Id | company_id | field 1 | field2 1 | 1 | somevalue1 | somevalue1 1 | 2 | somevalue1 | somevalue1 2 | 1 | somevalue2 | somevalue2 2 | 2 | somevalue2 | somevalue2
      
      





私の場合、データは特定のオフィスに属するという属性によって異なるはずであり、1つの条件でのSELECTのようなSQLクエリの複雑さは重要ではないため、このアプローチは最良と認識されました。



そして、それは簡単に思えます。複数のマスターサーバーと1つのスレーブサーバーが存在するマスタースレーブレプリケーションスキームがあり、ウィザードはバイナリログを使用してデータベースに行われたリクエストを送信します。両方のデータベースに一致します。 しかし、スレーブサーバーがどのリクエストが来たのか、どのリクエストが実行されたのか、どのリクエストが実行されなかったのかをどのように区別するのか自問しましょう。



実際には、各バイナリログには適切な名前のトランザクションの特定のセットが含まれているため、この問題はGTID(グローバルトランザクション識別子)によって解決されます。 レプリケーションチェーンに参加する各MySQLサーバーには、/ var / lib / mysql / auto.cnfファイルにある一意のserver-uuidが必要です。



 server-uuid=51164157-b6c9-11e5-bb7c-4e745964e860
      
      





さらに、マスターサーバーは、レプリケートされたデータベースで実行されるリクエストのトランザクションを生成するときに、それぞれに次のように番号を付けます。



 GTID = source_id:transaction_id 51164157-b6c9-11e5-bb7c-4e745964e860:23
      
      





将来これらの識別子の助けを借りて、ログを区別し、異なるサーバーからの競合するリクエスト間の競合を解決できるようになります。

主なポイントが合意されたので、次はビジネスに取り掛かり、サーバーのセットアップを開始します。 スタジオの構成。



マスターサーバーの構成:



 # Replication master settings # ID  server-id = 2 #         log-bin = /var/lib/mysql/mysql-bin.log #  GTID ,       server-uuid  auto.cnf gtid-mode = ON enforce-gtid-consistency = ON #     binlog-do-db = crm #      binlog-ignore-db = mysql binlog-ignore-db = sys binlog-ignore-db = performance_schema binlog-ignore-db = information_schema
      
      





レプリケーション用のユーザーを作成し、適切な権限を付与することを忘れないでください。



 CREATE USER 'slave_user'@'%' IDENTIFIED BY 'slavepass'; GRANT REPLICATION SLAVE ON *.* TO 'slave_user'@'%';
      
      





ウィザードのステータスを確認します。



 mysql> show master status; +------------------+----------+--------------+----------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+----------------------+-------------------+ | mysql-bin.000001 | 154 | crm | mysql,sys, | | | | | | performance_schema, | | | | | | information_schema | | +------------------+----------+--------------+----------------------+-------------------+ 1 row in set (0,00 sec)
      
      





スレーブサーバーの構成:



 # Replication Slave settings #   server-id = 1 #  GTID ,      auto.cnf   server-uuid gtid-mode = on enforce_gtid_consistency = on #        ,     master-info-repository = TABLE relay-log-info-repository = TABLE #     relay-log = /var/lib/mysql/mysql-relay-bin.log #   bin    log-bin = /var/lib/mysql/mysql-bin.log #     binlog-do-db = crm #       binlog-ignore-db = mysql binlog-ignore-db = sys binlog-ignore-db = information_schema binlog-ignore-db = performance_schema
      
      





レプリケーションを開始します。



 CHANGE MASTER TO MASTER_HOST='10.20.0.41', MASTER_USER='slave_user', MASTER_PORT=3306, MASTER_PASSWORD='slavepass', MASTER_AUTO_POSITION = 1 FOR CHANNEL 'master1'; CHANGE MASTER TO MASTER_HOST='10.20.0.42', MASTER_USER='slave_user', MASTER_PORT=3306, MASTER_PASSWORD='slavepass', MASTER_AUTO_POSITION = 1 FOR CHANNEL 'master2'; START SLAVE FOR CHANNEL "master1"; START SLAVE FOR CHANNEL "master2";
      
      





スレーブサーバーのステータスを確認します。



 SHOW SLAVE STATUS\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.20.0.41 Master_User: slave_user Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 154 Relay_Log_File: mysql-relay-bin-master1.000002 Relay_Log_Pos: 367 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 154 Relay_Log_Space: 582 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 3 Master_UUID: 73f11a40-b862-11e5-8b0c-1e80294d0535 Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: master1 Master_TLS_Version: *************************** 2. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 10.20.0.42 Master_User: slave_user Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 154 Relay_Log_File: mysql-relay-bin-master2.000002 Relay_Log_Pos: 367 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 154 Relay_Log_Space: 582 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0 Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 2 Master_UUID: 51164157-b6c9-11e5-bb7c-4e745964e860 Master_Info_File: mysql.slave_master_info SQL_Delay: 0 SQL_Remaining_Delay: NULL Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates Master_Retry_Count: 86400 Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 1 Replicate_Rewrite_DB: Channel_Name: master2 Master_TLS_Version: 2 rows in set (0,00 sec)
      
      





出来上がり、すべてが機能しますが、それが必要です。 皆さん、頑張ってください。




All Articles