一般的に、データベースの読み取りと書き込みがすべて同じデータベースサーバーで実行されると、ビジネスシステムのパフォーマンスが低下します。ビジネスシステムのパフォーマンスを向上させ、ユーザーエクスペリエンスを最適化するために、マスタースレーブレプリケーション(読み取り/書き込み分離)を使用して、メインデータベースの負荷を軽減できます。さらに、メインデータベースがダウンしている場合、ビジネスシステムをセカンダリデータベースにすばやく切り替えて、データの損失を回避できます。ソースコード:https://github.com/limingios/netFuture
マスタースレーブ同期を行う理由
- フェイルオーバーのためのリアルタイムのディザスタリカバリ
- 読み取りと書き込みの負荷分散
- スケジュールされたタスク専用
- 開発者ビュー
原則を理解する
次の図は、マスター/スレーブ同期の原理を示しています。
- webapp(つまり、Javaアプリケーション)は、メインライブラリmysqldに書き込みます。
1.1 mysqlデータノード
へのスロー1.2データステートメントはbinlogにスローされます(マスター/スレーブ同期を有効にするには、binlogをオンにする必要があります)selectクエリステートメントを除いて、レコードは記録されません。
1.3マスターノードmysqldには、対応するbinlogを生成するデータベースを指定できるフィルターがあります。それらはリアルタイム同期を必要としますが、そうではありません。
1.4 binlogs最後のハードディスクを生成し続けると、それは爆発しますか?そうでない場合、binlogsの有効期間を設定できます。以前に自動的に期限切れになるものを指定すると、自動的に削除されます。 - ライブラリから2つのスレッド、1つのI / Oスレッドと1つのSQLスレッドを生成します。
2.1 I / Oスレッドは、メインライブラリのbinlogを要求し、取得したbinlogをリレーログ(リレーログ)ファイルに書き込みます。
2.2リレーログはSQLスレッドによって読み取られ、binlogとデータを生成します。2.3
メインライブラリはログダンプスレッドを生成します。これは、binlogをスレーブライブラリのI / Oスレッドに転送するために使用されます。
2.4スレーブで生成されたbinlog(オープンまたはクローズ可能)は、別のスレーブで読み取ることができます。チェーンを形成します。 - 同期の原則であるbinlogには、マスターとスレーブに一貫性がない場合にノード(位置)があり、スレーブはデータを取得します。
問題と解決策
mysqlマスタースレーブレプリケーションの問題:
- メインライブラリがダウンした後、データが失われる可能性があります
- ライブラリからのSQLスレッドは1つだけであり、メインライブラリは高い書き込み圧力にさらされており、レプリケーションが遅延する可能性があります
解決する
- 準同期レプリケーション-データ損失の問題を解決します(マスターノードが前のステートメントを挿入すると、binlogがスレーブのリレーbinlogに到達します)
- プラグインの形でmysqlに統合された5.5は、個別にインストールする必要があります
- トランザクションがコミットされた後、binlogが少なくとも1つのスレーブライブラリに送信されることを確認します
- このトランザクションのbinlogがライブラリから適用されるという保証はありません
- パフォーマンスがある程度低下し、応答時間が長くなります
- ネットワークが異常であるか、スレーブライブラリがダウンしていて、マスターライブラリがタイムアウトするか、スレーブライブラリが回復するまでスタックします。
- 問題:スレーブがダウンしているとき、マスターは通信を続け、システム全体がジャンプする可能性があります。
解決策:
- マスターが通知を待機するタイムアウト期間は10秒です。10秒のスレーブ同期フラグが到着していない場合は、ローカルマスターのデータを挿入し続ける必要があります。
- しかし、多くの企業の99%は問題ないため、多くの企業は1秒を設定していますが、1秒の1%は問題です。この設定はビジネスによって異なります。建築家のレベルと経験。
一貫性と同期時間自体は両刃の剣です。完全なユニバーサルソリューションはありません。最適なソリューションは、ビジネスとパフォーマンスを包括的に検討することによってのみ選択できます。
マスターノードとスレーブノードが一貫性を持っている場合、比較してみましょう。マスターは皇帝であり、下には多くのスレーブ王子がいますが、スレーブの1人は王子でなければなりません。マスターが死ぬと、王子の1人が皇帝になります。
インターネット主流のマスタースレーブ方式
- 小規模企業では1つのマスターと1つのスレーブが使用され、読み取りと書き込みの分離はありません。スレーブノードは主にホットスタンバイです。問題はすぐに回復します。同僚が非常に重要なテーブルのデータを誤って削除したことを覚えています。20を超えるアイテムが削除された可能性があります。半月間はうまくいきませんでした。データの整合性の問題は解決されました。それらを1つずつ手動で見つけます。
- 小規模企業では、1つのマスターと複数のスレーブが使用されます。通常、マスターノードには3〜4つのスレーブノードがあります。3つのスレーブノードの1つはプリンスであり、データの整合性を確保できます。
- デュアルマスター、比較的異常、一般的には使用されない、デュアルマスターは、書き込みパフォーマンスが非常に高い場合、mysqlが許可されている場合、北京が1つのライブラリに書き込む場合、上海が1つのライブラリに書き込む場合に使用できますが、正直お勧めしません。
- カスケード同期、1つのマスター、1つのスレーブ(プリンス)ノード、および複数のスレーブノード。マスターがカスケードされていない場合は、読み取りと書き込み、および同期が必要です。マスターノードには大きなプレッシャーがかかります。カスケードとは、スレーブの1つを同期することです。これにより、マスターノードへの負荷が軽減され、マスターとスレーブの同期の問題も発生します。これにも問題があります。王子が電話を切ると、後ろの王子はリーダーなしで独立します。
- マスター-マスター-スレーブ、つまり2つのマスターが相互にアクセスします。後者のマスターはスレーブの同期に使用されますが、後者のマスターが電話を切ると、後者のスレーブもカスケード同期の状況と不自然に一致します。
- リングマルチマスター、非常に異常、絶対にお勧めしません。執筆の並行性は非常に高く、このようにプレイする方法はありません。全国に31の州、31のマスター、各州に1つのマスターがあります。マスターのいずれかが失敗すると、リング全体が停止します。マスターの下にスレーブを追加することもでき、超大型が使用されると推定されます。しかし、それはもう使用されません。
主流のワンマスターマルチスレーブソリューションを紹介します
これを実現するには、マスターが書き込みを担当し、スレーブが読み取りを担当します。負荷分散ソリューションが必要です。ここでアトラスについて話しましょう。シナリオモールで注文が生成された場合、すぐに読み取られます。従来の解決策では、スレーブライブラリを読み取る必要がありますが、現時点ではスレーブは同期を完了していません。これは恥ずかしいことですか?解決策はアトラスです。マスターで注文を生成し、それをすぐに読み取る必要がある場合は、SQLステートメントにコメントを追加するだけで、マスターに直接移動して読み取ることができます。
Atlasは、Qihoo360のWebプラットフォーム部門のインフラストラクチャチームによって開発および保守されているMySQLプロトコルに基づくデータ中間層プロジェクトです。MySQLによって正式にリリースされたMySQL-Proxy0.8.2バージョンに基づいて、多くのバグを修正し、多くの機能を追加しました。現在、このプロジェクトは360社で広く使用されています。多くのMySQLサービスがAtlasプラットフォームに接続されており、毎日実行される読み取りおよび書き込み要求の数は数十億に達します。同時に、50を超える企業が実稼働環境にAtlasを展開し、800を超える人々が開発者交換グループに参加しており、これらの数はまだ増え続けています。
Atlasの公式リンク:https://github.com/Qihoo360/Atlas/blob/master/README_ZH.md
Atlasのダウンロードリンク:https://github.com/Qihoo360/Atlas/releases
vagrantは仮想マシンを生成します
ソースコードから3つの仮想マシンを生成し、作業の準備をします。Vagrantは対応するDockerをインストールしました。dockerを使用してnexusをインストールすると、環境変数やユーザー認証などの複雑な操作を回避できます。さまざまなシステムに
vagrantをインストールする方法については、mac install vgarantを参照してください:https:
//idig8.com/2018/07/29/docker-zhongji-07/ window install vgarant https://idig8.com/2018/07 / 29 / docker-zhongji-08 /
システムタイプ | IPアドレス | ノードの役割 | CPU | 記憶 | ホスト名 |
---|---|---|---|---|---|
Centos7 | 192.168.66.101 | アトラスプロキシ | 2 | 2G | アトラスプロキシ |
Centos7 | 192.168.66.102 | 主人 | 2 | 2G | 主人 |
Centos7 | 192.168.66.103 | 奴隷 | 2 | 2G | 奴隷 |
- 3台のマシンwindow / macは、rootユーザーの下でリモートログインを有効にします
su -
# 密码
vagrant
#设置 PasswordAuthentication yes
vi /etc/ssh/sshd_config
sudo systemctl restart sshd
- ファイアウォールをオフにして無効にします(すべてのマシンが任意のポートを介して接続を確立できるようにするため)
指定ポートの実際の開口部に応じた実際の生産環境
systemctl stop firewalld
systemctl disable firewalld
#查看状态
systemctl status firewalld
102(マスター)、103(スレーブ)構成
プルミラー
docker pull mysql:5.7
102(マスター)構成
- 構成ディレクトリ
mkdir -p /usr/local/mysqlData/master/cnf
mkdir -p /usr/local/mysqlData/master/data
cd /usr/local/mysqlData/master/cnf
vi mysql.cnf
- mysql.cnfを構成します
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
symbolic-links=0
character-set-server = utf8
#skip-networking
innodb_print_all_deadlocks = 1
max_connections = 2000
max_connect_errors = 6000
open_files_limit = 65535
table_open_cache = 128
max_allowed_packet = 4M
binlog_cache_size = 1M
max_heap_table_size = 8M
tmp_table_size = 16M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
sort_buffer_size = 8M
join_buffer_size = 28M
key_buffer_size = 4M
thread_cache_size = 8
query_cache_type = 1
query_cache_size = 8M
query_cache_limit = 2M
ft_min_word_len = 4
log-bin = mysql-bin
server-id = 1
binlog_format = mixed
performance_schema = 0
explicit_defaults_for_timestamp
#lower_case_table_names = 1
interactive_timeout = 28800
wait_timeout = 28800
# Recommended in standard MySQL setup
sql_mode=NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER,STRICT_TRANS_TABLES
[mysqldump]
quick
max_allowed_packet = 16M
[myisamchk]
key_buffer_size = 8M
sort_buffer_size = 8M
read_buffer = 4M
write_buffer = 4M
- コンテナを起動します
docker images
docker run -itd -p 3306:3306 --name master \
-v /usr/local/mysqlData/master/cnf:/etc/mysql/conf.d \
-v /usr/local/mysqlData/master/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=masterpwd ae6b78bedf88
docker container ls
- コンテナを入力してリモートアクセスを有効にします
docker container ls
docker exec -it e2ca4d3cd633 /bin/bash
mysql -uroot -pmasterpwd
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'masterpwd' WITH GRANT OPTION;
GRANT REPLICATION SLAVE ON *.* to 'reader'@'%' identified by 'readerpwd';
FLUSH PRIVILEGES;
show master status;
103(スレーブ)構成
- 構成ディレクトリ
mkdir -p /usr/local/mysqlData/slave/cnf
mkdir -p /usr/local/mysqlData/slave/data
cd /usr/local/mysqlData/slave/cnf
vi mysql.cnf
- mysql.cnfを構成します
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
symbolic-links=0
character-set-server = utf8
#skip-networking
innodb_print_all_deadlocks = 1
max_connections = 2000
max_connect_errors = 6000
open_files_limit = 65535
table_open_cache = 128
max_allowed_packet = 4M
binlog_cache_size = 1M
max_heap_table_size = 8M
tmp_table_size = 16M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
sort_buffer_size = 8M
join_buffer_size = 28M
key_buffer_size = 4M
thread_cache_size = 8
query_cache_type = 1
query_cache_size = 8M
query_cache_limit = 2M
ft_min_word_len = 4
log-bin = mysql-bin
server-id = 2
binlog_format = mixed
performance_schema = 0
explicit_defaults_for_timestamp
#lower_case_table_names = 1
interactive_timeout = 28800
wait_timeout = 28800
# Recommended in standard MySQL setup
sql_mode=NO_ENGINE_SUBSTITUTION,NO_AUTO_CREATE_USER,STRICT_TRANS_TABLES
[mysqldump]
quick
max_allowed_packet = 16M
[myisamchk]
key_buffer_size = 8M
sort_buffer_size = 8M
read_buffer = 4M
write_buffer = 4M
- コンテナを起動します
docker images
docker run -itd -p 3307:3306 --name slave1 \
-v /usr/local/mysqlData/slave/cnf:/etc/mysql/conf.d \
-v /usr/local/mysqlData/slave/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=slavepwd ae6b78bedf88
docker container ls
- コンテナを入力してリモートアクセスを有効にします
リモート接続ユーザーを作成し、読み取りと書き込みの分離に使用できるクエリデータベースとクエリのアクセス許可を付与します。
docker container ls
docker exec -it c380d2b5f6cf /bin/bash
mysql -uroot -pslavepwd
grant SHOW DATABASES,SELECT on *.* to 'slave'@'%' identified by 'slavepwd';
FLUSH PRIVILEGES;
102masterのmysqlコンテナを入力します
メインライブラリを表示マスターステータスを表示
show master status
103slaveのmysqlコンテナを入力します
マスタースレーブを構成します。ここで一貫性を保つように、ステータス102のpostion = 889を構成する必要があります。
master_log_fileもメインライブラリと整合性がある必要があります
change master to master_host='192.168.66.102',master_user='reader',master_password='readerpwd',master_log_file='mysql-bin.000003',master_log_pos=889;
#启动主从
start slave;
show slave status\G
自動的に同期するデータベースを作成する
Atlasプロキシ構成(必要な場合にのみ使用します。上記が必要ない場合はそれで十分です)
Atlasプロキシを使用する場合は、mysqlパスワード102とmysqlパスワード103の一貫性を保つ必要があります。理由は、360が長期間維持されていないためです。問題の誰かが、複数を使用しているときに文字化けに遭遇しました。パスワード。103(スレーブ)構成(構成ディレクトリ、構成mysql.cnfは変更されません)
- 103スレーブmysqlを再削除して、新しいものを作成します
cd /usr/local/mysqlData/slave/data
rm -rf *
docker ps
docker rm -f c380d2b5f6cf
#这里的slave103的密码跟master102的密码一致
docker run -itd -p 3307:3306 --name slave1 \
-v /usr/local/mysqlData/slave/cnf:/etc/mysql/conf.d \
-v /usr/local/mysqlData/slave/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=masterpwd ae6b78bedf88
docker ps
- データベースのアクセス許可を変更する
docker ps
docker exec -it e698f50d7ece /bin/bash
mysql -uroot -pmasterpwd
- 102 mysqlと入力して、位置を表示します
#一定要记牢了,slave同步的时候要用,如果不一致就无法同步啦
show master status;
- 103コンテナ同期を入力します
docker ps
docker exec -it 6djasdad /bin/bash
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'masterpwd' WITH GRANT OPTION;
FLUSH PRIVILEGES;
change master to master_host='192.168.66.102',master_user='root',master_password='masterpwd',master_log_file='mysql-bin.000003',master_log_pos=1047;
#启动主从
start slave;
show slave status\G
スレーブホストでこれらの両方がyesの場合、構成は成功しています。
- 101ホストを入力して、プロキシの構成を開始します
wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
- パスワードの暗号化、構成ファイルが必要
cd /usr/local/mysql-proxy/
cd bin
./encrypt masterpwd
#下面就需要这个密码 test.cnf里面需要
XYx4FmVBYrXmTh762ogNww==
- アトラスファイルを構成する
vi /usr/local/mysql-proxy/conf/test.cnf
ここでは、pwdsに対応するパスワードが前の手順で生成され、ログレベルがデバッグ目的の適切なテストになるように設定されています。sql-log = REALTIMEは、SQLの方向を表示できます。
[mysql-proxy]
#带#号的为非必需的配置项目
#管理接口的用户名
admin-username = user
#管理接口的密码
admin-password = pwd
#Atlas后端连接的MySQL主库的IP和端口,可设置多项,用逗号分隔
proxy-backend-addresses = 192.168.66.102:3306
#Atlas后端连接的MySQL从库的IP和端口,@后面的数字代表权重,用来作负载均衡,若省略则默认为1,可设置多项,用逗号分隔
proxy-read-only-backend-addresses = 192.168.66.103:3307@1
#用户名与其对应的加密过的MySQL密码,密码使用PREFIX/bin目录下的加密程序encrypt加密,下行的user1和user2为示例,将其替换为你的MySQL的用户名和加密密码!
pwds = root:XYx4FmVBYrXmTh762ogNww==
#设置Atlas的运行方式,设为true时为守护进程方式,设为false时为前台方式,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
daemon = true
#设置Atlas的运行方式,设为true时Atlas会启动两个进程,一个为monitor,一个为worker,monitor在worker意外退出后会自动将其重启,设为false时只有worker,没有monitor,一般开发调试时设为false,线上运行时设为true,true后面不能有空格。
keepalive = true
#工作线程数,对Atlas的性能有很大影响,可根据情况适当设置
event-threads = 8
#日志级别,分为message、warning、critical、error、debug五个级别
log-level = debug
#日志存放的路径
log-path = /usr/local/mysql-proxy/log
#SQL日志的开关,可设置为OFF、ON、REALTIME,OFF代表不记录SQL日志,ON代表记录SQL日志,REALTIME代表记录SQL日志且实时写入磁盘,默认为OFF
sql-log = REALTIME
#慢日志输出设置。当设置了该参数时,则日志只输出执行时间超过sql-log-slow(单位:ms)的日志记录。不设置该参数则输出全部日志。
#sql-log-slow = 10
#实例名称,用于同一台机器上多个Atlas实例间的区分
#instance = test
#Atlas监听的工作接口IP和端口
proxy-address = 0.0.0.0:1234
#Atlas监听的管理接口IP和端口
admin-address = 0.0.0.0:2345
#分表设置,此例中person为库名,mt为表名,id为分表字段,3为子表数量,可设置多项,以逗号分隔,若不分表则不需要设置该项
#tables = person.mt.id.3
#默认字符集,设置该项后客户端不再需要执行SET NAMES语句
#charset = utf8
#允许连接Atlas的客户端的IP,可以是精确IP,也可以是IP段,以逗号分隔,若不设置该项则允许所有IP连接,否则只允许列表中的IP连接
#client-ips = 127.0.0.1, 192.168.1
#Atlas前面挂接的LVS的物理网卡的IP(注意不是虚IP),若有LVS且设置了client-ips则此项必须设置,否则可以不设置
#lvs-ips = 192.168.1.1
- アトラスを開始
cd /usr/local/mysql-proxy/bin/
# test 配置文件的名称 start 启动,stop 停止
./mysql-proxyd test start
デフォルトのリスニングポートは1234です。変更していません。変更する必要がある場合は、test.cnfを変更してください。
- ログを読み、テストの準備をします
cd /usr/local/mysql-proxy/log
tail -f sql_test.log
ついにこの写真を手に入れました
さらに、以前に遭遇した落とし穴は、フレームワークmybatisを使用してプロジェクト内のデータベースに接続するときに、メインライブラリに直接アクセスしてデータを読み書きしていました。トランザクション@Transactional
ソリューションが追加された場合、@ Transactional (propagation = Propagation.NOT_SUPPORTED)をメソッドに追加できます。
PS:実際、多くの企業はエージェントを介してマスタースレーブデータベースを管理しています。どのデータベースから移動するかを選択的に制御できます。気持ちいい、102はインサート、103はセレクト。