【純幹貨】Amoeba實現MySQL主從同步與讀寫分離
一、簡介
- amoeba簡介
Amoeba(變形蟲)項目,該開源框架於2008年開始發布一款 Amoeba for Mysql軟件。這個軟件致力於MySQL的分布式數據庫前端代理層,它主要在應用層訪問MySQL的 時候充當SQL路由功能,專註於分布式數據庫代理層(Database Proxy)開發。座落與 Client、DB Server(s)之間,對客戶端透明。具有負載均衡、高可用性、SQL 過濾、讀寫分離、可路由相關的到目標數據庫、可並發請求多臺數據庫合並結果。 通過Amoeba你能夠完成多數據源的高可用、負載均衡、數據切片的功能,目前Amoeba已在很多企業的生產線上面使用
- Amoeba的優缺點
優點:
(1)降低費用,簡單易用
(2)提高系統整體可用性
(3)易於擴展處理能力與系統規模
(4)可以直接實現讀寫分離及負載均衡效果,而不用修改代碼
缺點:
(1)不支持事務與存儲過程
(2)暫不支持分庫分表,amoeba目前只做到分數據庫實例
(3)不適合從amoeba導數據的場景或者對大數據量查詢的query並不合適(比如一次請求返回10w以上甚至更多數據的場合)
3.什麽是讀寫分離
讀寫分離(Read/Write Splitting),基本的原理是讓主數據庫處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從數據庫處理SELECT查詢操作。
數據庫復制被用來把事務性操作導致的變更同步到集群中的從數據庫。
二、實驗拓撲構架
client linux6-1 IP:192.168.234.186
主MySQL centos7-1 IP:192.168.234.174
從MySQL01 centos7-2 IP:192.168.234.177
從MySQL02 centos7-5 IP:192.168.234.184
amoeba服務器 centos7-3 IP:192.168.234.181
讀寫分離實驗配置
源碼編譯安裝MySQL5.5
- 編譯MySQL5.5的依賴環境包
yum install gcc 、 gcc-c++ 、make、cmake
ncurses-devel、bison、libaio-devel -y
- 創建MySQL用戶
groupadd -r mysql
useradd -g mysql -r -d /mydata/data mysql
- 源碼編譯MySQL
tar zxvf mysql-5.5.24.tar.gz -C /opt
cd /opt/mysql-5.5.24.tar.gz
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql
-DMYSQL_UNIX_ADDR=/home/mysql/mysql.sock
-DDEFAULT_CHARSET=utf8
-DDEFAULT_COLLATION=utf8_general_ci
-DWITH_EXTRA_CHARSETS=all
-DWITH_MYISAM_STORAGE_ENGINE=1
-DWITH_INNOBASE_STORAGE_ENGINE=1
-DWITH_MEMORY_STORAGE_ENGINE=1
-DWITH_READLINE=1
-DENABLED_LOCAL_INFILE=1
-DMYSQL_DATADIR=/home/mysql
-DMYSQL_USER=mysql
-DMYSQL_TCP_PORT=3306
make && make install
4.更改mysql的主目錄為mysql組
chown -R mysql.mysql /usr/local/mysql
5.配置mysql環境變量
echo "export PATH=\$PATH:/usr/local/mysql/bin" > /etc/profile.d/mysql.sh
source /etc/profile.d/mysql.sh
6.復制MySQL啟動腳本和服務配置文件分別到/etc/my.cnf和/etc/init.d/mysqld
cp support-files/my-medium.cnf /etc/my.cnf
cp support-files/mysql.server /etc/init.d/mysqld
7.給予相應的權限並且加入開機自啟動項
chmod 755 /etc/init.d/mysqld
chkconfig --add /etc/init.d/mysqld
chkconfig mysqld --level 35 on
8.初始化數據庫
/usr/local/mysql/scripts/mysql_install_db \
--user=mysql \
--ldata=/var/lib/mysql \
--basedir=/usr/local/mysql \
--datadir=/home/mysql
9.建立軟鏈接
ln -s /var/lib/mysql/mysql.sock /home/mysql/mysql.sock
10.配置啟動腳本
vim /etc/init.d/mysqld
basedir=/usr/local/mysql
datadir=/home/mysql
11.啟動MySQL服務
systemctl start mysqld.service
12.設置MySQL用戶的密碼
mysqladmin -u root password ‘abc123‘
MySQL主服務器(master CentOS7-1)配置
[root@localhost ~]# vim /etc/my.cnf
...省略
log-bin=master-bin //這裏原來的mysql修改為master
log-slave-updates=true //添加,表示從服務器更新二進制日誌
...省略
server-id = 11
重新啟動mysql服務,並且給予從服務器訪問權限
[root@localhost ~]# systemctl restart mysqld.service //重啟MySQL服務
[root@localhost ~]# mysql -u root -p
Enter password:
mysql> GRANT REPLICATION SLAVE ON *.* TO ‘myslave‘@‘192.168.234.%‘ IDENTIFIED BY ‘123456‘; //給予從服務器訪問權限
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges; //刷新生成二進制文件
Query OK, 0 rows affected (0.00 sec)
mysql> show master status; //查看pos偏移量
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 | 477 | | |
+-------------------+----------+--------------+------------------+
1 row in set (0.01 sec)
從服務器(slave CentOS7-2)配置
[root@localhost ~]# systemctl stop firewalld.service
localhost ~]# setenforce 0
[root@localhost ~]# yum install ntpdate -y
[root@localhost ~]# systemctl start ntpd.service
[root@localhost ~]# vim /etc/my.cnf
...省略
server-id = 22
relay-log=relay-log-bin //從主服務器上同步日誌文件記錄到本地
relay-log-index=slave-relay-bin.index //定義relay-log的位置和名稱
重啟MySQL服務,並且指定從服務器同步的對象服務器
[root@localhost ~]# mysql -u root -p
Enter password:
mysql> change master to master_host=‘192.168.234.174‘,master_user=‘myslave‘,master_password=‘123456‘,master_log_file=‘master-bin.000001‘,master_log_pos=477; //設置同步的對象服務器及用戶密碼
Query OK, 0 rows affected (0.01 sec)
mysql> start slave; //開啟主從同步
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G; //查看slave狀態
*************************** 1. row ***************************
Slave_IO_State: Reconnecting after a failed master event read
Master_Host: 192.168.234.174
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000001
Read_Master_Log_Pos: 564
Relay_Log_File: localhost-relay-bin.001259
Relay_Log_Pos: 254
Relay_Master_Log_File: master-bin.000001
Slave_IO_Running: Yes //這裏必須是yes
Slave_SQL_Running: Yes //這裏必須是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: 564
Relay_Log_Space: 561
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: 1360
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: 11
1 row in set (0.00 sec)
從服務器2(slave2 CentOS7-5)和上面一樣的配置
驗證主從同步
在主服務器上添加一個數據庫school,查看兩個從服務器是否能夠同步獲取到school數據庫
主服務器添加數據庫school
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| #mysql50#.mozilla |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.01 sec)
mysql> create database school; //添加school數據庫
Query OK, 1 row affected (0.00 sec)
在兩臺從服務器上查看是否同步獲取到school數據庫
slave1 CentOS7-2
mysql> show databases; //查看有哪些數據庫
+--------------------+
| Database |
+--------------------+
| information_schema |
| #mysql50#.mozilla |
| mysql |
| performance_schema |
| school | //這裏就同步獲取到school數據庫
| test |
+--------------------+
6 rows in set (0.01 sec)
slave2 CentOS7-5
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| #mysql50#.mozilla |
| mysql |
| performance_schema |
| school | //這裏slave2也同步獲取到一個school的數據庫
| test |
+--------------------+
6 rows in set (0.00 sec)
到這裏如果兩臺從服務器都能獲取到school數據庫,就說明主從同步已經沒問題了,那麽接下來就是在amoeba服務器(CentOS7-3)上部署讀寫分離了
amoeba服務器(CentOS7-3)的部署設置
因為Amoeba是java程序開發的,所以Amoeba服務器上要先安裝jdk環境
[root@localhost ~]# systemctl stop firewalld.service
[root@localhost ~]# setenforce 0
[root@localhost mysql]# cp jdk-6u14-linux-x64.bin /usr/local/
[root@localhost mysql]# ./jdk-6u14-linux-x64.bin
。。。省略
Do you agree to the above license terms? [yes or no]
y //前面一直按Enter直到這裏輸入y(yes),然後就等jdk環境安裝完成
然後安裝Amoeba服務
[root@localhost local]# mv jdk1.6.0_14/ jdk1.6
[root@localhost local]# vim /etc/profile //添加amoeba的環境變量
//G到行尾添加
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin
[root@localhost local]# source /etc/profile //刷星使環境變量立即生效
[root@localhost local]# mkdir /usr/local/amoeba //創建一個amoeba的工作目錄
[root@localhost local]# tar zxvf /abc/mysql/amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/ //解壓安裝amoeba至工作目錄
[root@localhost local]# chmod -R 755 amoeba/ //遞歸給予amoeba及子文件執行權限
[root@localhost local]# /usr/local/amoeba/bin/amoeba //檢查amoeba是否安裝成功
amoeba start|stop //看到這樣的提示就說明amoeba服務安裝完成
然後在三臺MySQL服務器上添加權限開放給amoeba訪問,用戶使用test,密碼是123123
grant all on . to test@‘192.168.234.%‘ identified by ‘123123‘;
修改amoeba服務器的配置文件
[root@localhost amoeba]# vim conf/amoeba.xml
。。。省略
<!-- --> //刪除這裏,表示開啟
30 <property name="user">amoeba</proper ty> //這裏修改用戶為之前設置的amoeba
31 <!-- --> //刪除這裏,表示開啟
32 <property name="password">123456</pr operty> //添加密碼為之前設置的密碼123456
33
。。。省略
115 <property name="defaultPool">master</property> //這裏修改為默認使用master主服務器
116
117
118 <property name="writePool">master</property> //允許主服務器寫入
119 <property name="readPool">slaves</property> //允許從服務器讀取
[root@localhost amoeba]# vim conf/dbServers.xml //修改數據庫的配置文件
<!-- mysql user -->
26 <property name="user">test</property> //這裏修改為test,即使用test用戶去讀取MySQL的數據
27 <!-- mysql pseeword //這裏有一個<!--表示註釋的意思,所以要刪除
28 <property name="password">123123</property> //密碼為前面設置的密碼123123
--> //刪除
<dbServer name="master" parent="abstractServer"> //修改原來的server1為master
45 <factoryConfig>
46 <!-- mysql ip -->
47 <property name="ipAddress">192.168.234.174</property> //這裏改為主服務器的IP地址
48 </factoryConfig>
49 </dbServer>
50
51 <dbServer name="slave1" parent="abstractServer"> //server2改為slave1
52 <factoryConfig>
53 <!-- mysql ip -->
54 <property name="ipAddress">192.168.234.177</property> //slave1(即CentOS7-2)IP地址
55 </factoryConfig>
56 </dbServer>
57 #添加
58 <dbServer name="slave2" parent="abstractServer">
59 <factoryConfig>
60 <!-- mysql ip -->
61 <property name="ipAddress">192.168.234.184</property> //slave2(即CentOS7-5)IP地址
62 </factoryConfig>
64 <dbServer name="slaves" virtual="true"> //服務器池名為slaves
65 <poolConfig class="com.meidusa.amoeba.server.MultipleServerP ool">
66 <!-- Load balancing strategy: 1=ROUNDROBIN , 2=WEIGH TBASED , 3=HA-->
67 <property name="loadbalance">1</property>
68
69 <!-- Separated by commas,such as: server1,server2,se rver1 -->
70 <property name="poolNames">slave1,slave2</property> //服務器池內的兩臺服務器的名稱
71 </poolConfig>
72 </dbServer>
開啟amoeba服務,並且檢查端口是否開啟
[root@localhost amoeba]# /usr/local/amoeba/bin/amoeba start & //開啟amoeba服務器,並且放入後臺執行
[2] 3996
[root@localhost amoeba]# log4j:WARN log4j config load completed from file:/usr/local/amoeba/conf/log4j.xml
2018-07-08 15:02:45,493 INFO context.MysqlRuntimeContext - Amoeba for Mysql current versoin=5.1.45-mysql-amoeba-proxy-2.2.0
log4j:WARN ip access config load completed from file:/usr/local/amoeba/conf/access_list.conf
2018-07-08 15:02:46,450 INFO net.ServerableConnectionManager - Amoeba for Mysql listening on 0.0.0.0/0.0.0.0:8066. //這裏可以看到開始監聽端口8066
2018-07-08 15:02:46,476 INFO net.ServerableConnectionManager - Amoeba Monitor Server listening on /127.0.0.1:38438.
^C
[root@localhost amoeba]# netstat -ntap | grep java //查看java的程序
tcp6 0 0 :::8066 :::* LISTEN 3996/java //然後就可以看到有一個8066的端口已經開啟了
tcp6 0 0 127.0.0.1:38438 :::* LISTEN 3996/java
tcp6 0 0 192.168.234.181:37510 192.168.234.174:3306 ESTABLISHED 3996/java
tcp6 0 0 192.168.234.181:38208 192.168.234.177:3306 ESTABLISHED 3996/java
tcp6 0 0 192.168.234.181:47642 192.168.234.184:3306 ESTABLISHED 3996/java
然後這裏該部署的部署完成了,剩下的就是驗證是否能夠實現讀寫分離了
驗證
這裏先簡單說明下驗證過程:先在主服務器的school庫中創建一個表zyc,然後兩臺從服務器關閉slave,在主服務器的zyc表中插入數據1,從服務器1的zyc表(註:創建表時同步並未關閉,所以從服務器會同步生成一個zyc表)中插入數據2,從服務器2的zyc表中插入數據3,然後使用客戶機Linux6-1訪問amoeba服務器,會看到顯示的數據會在兩個從服務器的2、3數據間切換,並不會顯示主服務器寫入的數據1;在客戶機Linux6-1上寫入數據,然後只有在主MySQL服務器能查詢到,兩個從服務器卻查看不到;最後開啟兩個從服務器的同步,在客戶機查看數據,就會看到數據顯示為214、314間切換。
//主服務器添加表
mysql> create table zyc (id int(5),name varchar(10));
Query OK, 0 rows affected (0.03 sec)
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| zyc |
+------------------+
1 row in set (0.00 sec)
//兩個從服務器即會同步獲取表信息
#從服務器1 CentOS7-2
mysql> use school;
Database changed
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| zyc |
+------------------+
1 row in set (0.00 sec)
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
#從服務器2 CentOS7-5
mysql> use school;
Database changed
mysql> show tables;
+------------------+
| Tables_in_school |
+------------------+
| zyc |
+------------------+
1 row in set (0.01 sec)
mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)
#主服務器插入數據1
mysql> insert into zyc values (1,‘zhangsan‘);
Query OK, 1 row affected (0.01 sec)
mysql> select * from zyc;
+------+----------+
| id | name |
+------+----------+
| 1 | zhangsan |
+------+----------+
1 row in set (0.00 sec)
#從服務器1插入數據2
mysql> insert into zyc values (2,‘lisi‘);
Query OK, 1 row affected (0.01 sec)
mysql> select * from zyc;
+------+------+
| id | name |
+------+------+
| 2 | lisi |
+------+------+
1 row in set (0.01 sec)
#從服務器2插入數據3
mysql> insert into zyc values (3,‘wangwu‘);
Query OK, 1 row affected (0.01 sec)
mysql> select * from zyc;
+------+--------+
| id | name |
+------+--------+
| 3 | wangwu |
+------+--------+
1 row in set (0.00 sec)
#此時使用客戶機去訪問amoeba服務器會看到數據只顯示兩個從服務器的
mysql> select * from zyc;
+------+--------+
| id | name |
+------+--------+
| 2 | lisi |
+------+--------+
1 row in set (0.00 sec)
mysql> select * from zyc;
+------+--------+
| id | name |
+------+--------+
| 3 | wangwu |
+------+--------+
1 row in set (0.00 sec)
#然後打開兩個從服務器的同步,在客戶機插入數據4
mysql> insert into zyc values (4,‘zhaoliu‘);
Query OK, 1 row affected (0.01 sec)
select * from zyc;
+------+----------+
| id | name |
+------+----------+
| 2 | lisi |
+------+----------+
| 1 | zhangsan |
+------+----------+
| 4 | zhaoliu |
+------+----------+
select * from zyc;
+------+----------+
| id | name |
+------+----------+
| 3 | wangwu |
+------+----------+
| 1 | zhangsan |
+------+----------+
| 4 | zhaoliu |
+------+----------+
最後的實驗結論為:主服務器負責寫入數據;從服務器負責讀取數據;且兩個從服務器會與主服務器進行同步,而兩個從服務器間則不會同步
如果您實驗到最後得到的也是這樣的結果,那麽恭喜您讀寫分離的實驗您成功了!
這樣就實現了MySQL的讀寫分離及主從同步
【純幹貨】Amoeba實現MySQL主從同步與讀寫分離