記事ディレクトリ
1.読み書きの分離の原則
1.1理由
- エンタープライズアプリケーションでは、多数のデータリクエストの下で、単一のデータベースがすべての読み取りおよび書き込み操作を実行できません。
- 複数のデータベースサーバーを構成して、読み取りと書き込みの分離を実現する
- 読み取りと書き込みの分離は、マスターとスレーブのレプリケーションに基づいています
1.2原則
- 読み取りと書き込みの分離では、マスターサーバーにのみ書き込み、スレーブサーバーでのみ読み取りを行います。
- メインデータベースはトランザクションクエリを処理し、スレーブデータベースは選択クエリを処理します
- データベースレプリケーションは、トランザクションクエリによって引き起こされた変更をクラスター内のスレーブデータベースに同期するために使用されます。
現在、より一般的なMySQLの読み取りと書き込みの分離は、2つのタイプに分かれています。
(1)プログラムコードの内部実装に基づいて、
ルーティングの分類は、コードの選択と挿入に従って実行されます。このタイプのメソッドは、現在の本番環境でも広く使用されています。
プログラムコードで実装されるため、ハードウェア支出として追加の機器を追加する必要はありません。デメリットは、開発者が実装する必要があり、運用および保守担当者が開始できないことです。
(2)中間プロキシ層に基づく実現
プロキシは通常、クライアントとサーバーの間にあり、プロキシサーバーはクライアントのリクエストを受信し、判断を通過した後、バックエンドデータベースに転送します。代表的なプログラムは2つあります。
- MySQL-Proxy。---- MySQLはオープンソースプロジェクトであり、SQLの判断は組み込みのluaスクリプトを介して行われます。MySQLは正式にこれを本番環境で使用することを推奨していません
- Amoeba(Amoeba)---- Chen Siruが開発し、かつてAlibabaで働いていたプログラムはJava言語で開発されており、Alibabaは本番環境で使用します
ただし、物事やストアドプロシージャはサポートしていません。
2、MySQLマスタースレーブレプリケーションの原則と構成
前のブログで説明したように、このケースの実装はマスター/スレーブレプリケーションに基づいています。詳細については、https://blog.csdn.net/ZG_66/article/details/108578383を参照してください。
3、実験
3.1。環境の準備
試験運用環境のファイアウォールとコア保護がオフになっています
systemctl stop firewalld.service
setenforce 0
3.1.1、VMwareホスト
5つのcentos7.6ホスト、
1つはクライアントIPアドレス20.0.0.25用、
1つはamoeba IPアドレスは20.0.0.24、1
つのマスターmysqlサーバーのIPアドレスは20.0.0.21、2
つのスレーブmysqlサーバーのIPアドレスは20.0.0.22および20.0.0.23
3.1.2、トポロジー図
3.1.3、実験目的
読み取りと書き込みの分離を実現
3.2。実験プロセス
3.2.1、mysqlマスター/スレーブレプリケーション環境を構築する
Mysqlマスターとスレーブによってコピーされたブログアドレス:https : //blog.csdn.net/ZG_66/article/details/108578383
3.2.2、Amoeba(20.0.0.24)のインストールと構成
(1)元のJava環境をアンインストールします
[root@amoeba ~]# java -version ##确定java版本 1.8.0_181的 有点高
openjdk version "1.8.0_181"
OpenJDK Runtime Environment (build 1.8.0_181-b13)
OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)
[root@amoeba ~]# rpm -qa |grep java
java-1.8.0-openjdk-headless-1.8.0.181-7.b13.el7.x86_64 ####卸载
tzdata-java-2018e-3.el7.noarch
python-javapackages-3.4.1-11.el7.noarch
java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64 ####卸载
javapackages-tools-3.4.1-11.el7.noarch
java-1.7.0-openjdk-1.7.0.191-2.6.15.5.el7.x86_64 ####卸载
java-1.7.0-openjdk-headless-1.7.0.191-2.6.15.5.el7.x86_6 ####卸载
[root@amoeba ~]# rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0.181-7.b13.el7.x86_64
[root@amoeba ~]# rpm -e --nodeps java-1.8.0-openjdk-1.8.0.181-7.b13.el7.x86_64
[root@amoeba ~]# rpm -e --nodeps java-1.7.0-openjdk-1.7.0.191-2.6.15.5.el7.x86_64
[root@amoeba ~]# rpm -e --nodeps java-1.7.0-openjdk-headless-1.7.0.191-2.6.15.5.el7.x86_64
(2)JDKをインストール
し、optディレクトリにJDKをアップロードします
[root@amoeba ~]# cd /opt
[root@amoeba opt]# tar xzvf jdk-8u144-linux-x64.tar.gz
[root@amoeba opt]# cp -rv jdk1.8.0_144/ /usr/local/java
[root@amoeba opt]# vi /etc/profile //在最后添加下面四行
export JAVA_HOME=/usr/local/java
export JRE_HOME=/usr/local/java/jre
export PATH=$PATH:/usr/local/java/bin
export CLASSPATH=./:/usr/local/java/lib:/usr/local/java/jre/lib
[root@amoeba opt]# source /etc/profile
[root@amoeba opt]# java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
(3)amoebaをインストール
し、パッケージをoptディレクトリにアップロードします
[root@amoeba opt]# unzip amoeba-mysql-3.0.5-RC-distribution.zip -d /usr/local/
[root@amoeba opt]# mv /usr/local/amoeba-mysql-3.0.5-RC/ /usr/local/amoeba
[root@amoeba opt]# chmod -R 755 /usr/local/amoeba/
[root@amoeba opt]# vi /usr/local/amoeba/jvm.properties
JVM_OPTIONS="-server -Xms256m -Xmx1024m -Xss196k -XX:PermSize=16m -XX:MaxPermSize=96m" //32行修改成如下
JVM_OPTIONS="-server -Xms1024m -Xmx1024m -Xss256k"
(4)アメーバ管理スクリプトを作成する
[root@amoeba opt]# vi /etc/init.d/amoeba
#!/bin/bash
#chkconfig: 35 62 62
#
export JAVA_HOME=/usr/local/java
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH
NAME=Amoeba
AMOEBA_BIN=/usr/local/amoeba/bin/launcher
SHUTDOWN_BIN=/usr/local/amoeba/bin/shutdown
PIDFILE=/usr/local/amoeba/Amoeba-MySQL.pid
SCRIPTNAME=/etc/init.d/amoeba
case "$1" in
start)
echo -n "Starting $NAME... "
$AMOEBA_BIN
echo " done"
;;
stop)
echo -n "Stoping $NAME... "
$SHUTDOWN_BIN
echo " done"
;;
restart)
$SHUTDOWN_BIN
sleep 1
$AMOEBA_BIN
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart}"
exit 1
;;
esac
"/etc/rc.d/init.d/amoeba" [New] 32L, 544C written
[root@amoeba opt]# chmod +x /etc/init.d/amoeba
[root@amoeba opt]# chkconfig --add amoeba
[root@amoeba opt]# service amoeba start
[root@amoeba opt]# netstat -anpt | grep 8066
tcp6 0 0 :::8066 :::* LISTEN 20226/java
3.2.3。分離を読み書きするようにアメーバを構成し、負荷バランスを読み取るように2つのスレーブを構成する
(1)3つのmysqlサーバーに権限を追加し、
メイン(20.0.0.21)端末にアクセスするためにユーザーをamoebaに開きます。
[root@master ~]# mysql -u root -p
Enter password:
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> GRANT ALL ON *.* TO test@'20.0.0.%' IDENTIFIED BY 'abc123';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
1(20.0.0.22)端末からログイン
[root@slave1 ~]# mysql -u root -p
Enter password:
mysql> GRANT ALL ON *.* TO test@'20.0.0.%' IDENTIFIED BY 'abc123';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)
2(20.0.0.23)端末からログイン
[root@slave2 ~]# mysql -u root -p
Enter password:
mysql> GRANT ALL ON *.* TO test@'20.0.0.%' IDENTIFIED BY 'abc123';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.02 sec)
(2)amoebaサーバーの設定
[root@amoeba opt]# cd /usr/local/amoeba
[root@amoeba amoeba]# vi conf/amoeba.xml
---28行-----设置客户端连接amoeba前端服务器时使用的用户名和密码----
<property name="user">amoeba</property>
----30行---------
<property name="password">123456</property>
------------------------------------以上配置用于客户端连接用户名密码-------------
---83-去掉注释-同时把默认的server1改成master,把默认的servers改成 slaves
<property name="defaultPool">master</property>
<property name="writePool">master</property>
<property name="readPool">slaves</property>
######上面修改后如下#### <!-- --> 这种注释一定要去掉
82 <property name="LRUMapSize">1500</property>
83 <property name="defaultPool">master</property>
84 <property name="writePool">master</property>
85 <property name="readPool">slaves</property>
86 <property name="needParse">true</property>
[root@amoeba amoeba]# vi conf/dbServers.xml
--26-29--去掉注释--
<property name="user">test</property>
<property name="password">abc123</property>
------主服务器地址---
43 <dbServer name="master" parent="abstractServer">
46 <property name="ipAddress">20.0.0.21</property>
--50-从服务器主机名-
<dbServer name="slave1" parent="abstractServer">
--53-从服务器地址-
<property name="ipAddress">20.0.0.22</property>
-----------------省略------------------------
<!-- mysql port -->
<property name="port">3306</property>
<!-- mysql schema -->
<property name="schema">test</property>
<!-- mysql user -->
<property name="user">test</property> #####user 后面改成test 这边是mysql数据库授权账户
<property name="password">abc123</property> #####password 后面改成abc123 这是mysql数据库授权密码
</factoryConfig>
--------------省略-------------------------
<dbServer name="master" parent="abstractServer"> #####name后面改成 master
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">20.0.0.21</property> ####ipAddress加上主mysql的IP地址
</factoryConfig>
</dbServer>
<dbServer name="slave1" parent="abstractServer"> #####name后面改成 slave1
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">20.0.0.22</property> ###ipAddress加上从1mysql的IP地址
</factoryConfig>
</dbServer>
###注意啦!在脚本中slave2是没有的,需要复制下#####
<dbServer name="slave2" parent="abstractServer"> #####name后面改成 slave2
<factoryConfig>
<!-- mysql ip -->
<property name="ipAddress">20.0.0.23</property> ###ipAddress加上从2mysql的IP地址
</factoryConfig>
</dbServer>
<dbServer name="slaves" virtual="true"> #####name后面改成 slaves
<poolConfig class="com.meidusa.amoeba.server.MultipleServerPool">
<!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGHTBASED , 3=HA-->
<property name="loadbalance">1</property>
<!-- Separated by commas,such as: server1,server2,server1 -->
<property name="poolNames">slave1,slave2</property> #####poolNames后面改成 slave1,slave2
</poolConfig>
</dbServer>
-----------------------注意----------------------
<!-- mysql schema -->
<property name="schema">test</property> //数据库中要有此处定义的数据库,否则客户端连接后会报如下错误:
ERROR 1044 (42000): Could not create a validated object, cause: ValidateObject failed
(3)Amoebaソフトウェアを起動する
[root@amoeba amoeba]# service amoeba restart
[root@amoeba amoeba]# netstat -anpt | grep java
tcp6 0 0 :::8066 :::* LISTEN 72410/java
tcp6 0 0 20.0.0.24:60102 20.0.0.21:3306 ESTABLISHED 72410/java
tcp6 0 0 20.0.0.24:52726 20.0.0.22:3306 ESTABLISHED 72410/java
tcp6 0 0 20.0.0.24:43044 20.0.0.23:3306 ESTABLISHED 72410/java
3.2.4、検証
(1)クライアントは
検証用にmysql をインストールするため、yumで直接インストールできます
[root@client ~]# yum install -y mysql
[root@client ~]# mysql -u amoeba -p123456 -h 20.0.0.24 -P8066
(2)メインのmysqlにデータベース20.0.0.21を作成します
[root@master ~]# mysql -u root -p
Enter password:
mysql> use test;
Database changed
mysql> create table zhang1 (id int(10),name varchar(10),address varchar(20));
Query OK, 0 rows affected (0.00 sec)
(3)1 mysqlから同期20.0.0.22をオフにする
[root@slave1 ~]# mysql -u root -p
Enter password:
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> insert into zhang1 values('2','zhang','this_is_slave1');
Query OK, 1 row affected (0.00 sec)
(4)2 mysqlから同期20.0.0.23をオフにする
[root@slave2 ~]# mysql -u root -p
Enter password:
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> use test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> insert into zhang1 values('3','zhang','this_is_slave2');
Query OK, 1 row affected (0.00 sec)
(5)メインのmysqlにデータ20.0.0.21を挿入します
mysql> insert into zhang1 values('1','zhang','this_is_master');
Query OK, 1 row affected (0.01 sec)
(6)クライアントにログイン20.0.0.25
[root@client ~]# mysql -u amoeba -p123456 -h 20.0.0.24 -P8066
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| lx |
| mysql |
| performance_schema |
| sys |
| test |
+--------------------+
6 rows in set (0.01 sec)
MySQL [(none)]> use test;
Database changed
MySQL [test]> select * from zhang1;
+------+-------+----------------+
| id | name | address |
+------+-------+----------------+
| 2 | zhang | this_is_slave1 |
+------+-------+----------------+
1 row in set (0.00 sec)
MySQL [test]> select * from zhang1;
+------+-------+----------------+
| id | name | address |
+------+-------+----------------+
| 3 | zhang | this_is_slave2 |
+------+-------+----------------+
1 row in set (0.00 sec)
上記の実験は、データ読み取りの負荷分散を実現します
(7)クライアントの20.0.0.25でデータの書き込みを続行します。通常のルールによれば、slave1とslave2は非表示になります。
MySQL [test]> insert into zhang1 values('4','zhang','write_test');
mastar 20.0.0.21にログイン
mysql> select * from zhang1;
+------+-------+----------------+
| id | name | address |
+------+-------+----------------+
| 1 | zhang | this_is_master |
| 4 | zhang | write_test |
+------+-------+----------------+
2 rows in set (0.00 sec)
slave1 20.0.0.22にログインします。
mysql> select * from zhang1;
+------+-------+----------------+
| id | name | address |
+------+-------+----------------+
| 2 | zhang | this_is_slave1 |
+------+-------+----------------+
1 row in set (0.00 sec)
slave2 20.0.0.23にログインします。
mysql> select * from zhang1;
+------+-------+----------------+
| id | name | address |
+------+-------+----------------+
| 3 | zhang | this_is_slave2 |
+------+-------+----------------+
1 row in set (0.00 sec)
上記の検証結果は次のとおりです。
クライアント(20.0.0.25)にデータを書き込むように操作すると、データがマスターに書き込まれ、書き込まれたデータはsalve1とslave2に表示されません。