Mysql讀寫分離——主從資料庫+Atlas
mysql叢集
最近在參加專案開發微信小程式後臺,由於使用者數量巨大,且後臺程式並不是很完美,所以對使用者的體驗很是不友好(簡單說就是很卡)。趕巧最近正在翻閱《大型網站系統與Java中介軟體實踐》。 所以,先是使用Docker swarm構建了負載均衡叢集,然後使用Atlas做了資料庫的讀寫分離,儘可能對使用者進行分流,降低對單機伺服器的負載,提高訪問體驗。本片隨筆僅對資料庫的讀寫分離部分進行介紹。
目標:實現mysql資料庫叢集,一個主節點負責寫入資料,多個從節點負責讀取資料
實驗環境
伺服器:
- 阿里雲伺服器:centos7(10.0.0.1)
- 騰訊雲伺服器:ubuntu:16.04(10.0.0.2)
- 京東雲伺服器:ubuntu:16.04 (10.0.0.3)
mysql:5.7
docker:18.03
實現方案
mysql 主從資料庫 + Atlas讀寫分離
步驟:
進入Master伺服器進行配置
- 使用Docker,在伺服器上建立MySQL服務
docker run -p 3306:3306 --name mysql3306 -v /opt/mysql/data/data3306:/var/lib/mysql -v /opt/mysql/logs/logs3306:/logs -e MYSQL_ROOT_PASSWORD=hello -d mysql:5.7
- 進Master伺服器的MySQL資料庫中,建立使用者"niwoo"設定密碼為"hello"
mysql -h 127.0.0.1 -uroot -phello
mysql> grant all on *.* to [email protected]'127.0.0.1' identified by "hello";
Query OK, 0 rows affected, 1 warning (0.00 sec)
- 修改niwoo的訪問許可權
mysql> use mysql 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> update user set host = '%' where user = 'ninwoo'; Query OK, 0 rows affected (0.00 sec) Rows matched: 0 Changed: 0 Warnings: 0
- 確認是否修改成功
mysql> update user set host = '%' where user = 'ninwoo';
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select user, host from user;
+---------------+-----------+
| user | host |
+---------------+-----------+
| ninwoo | % |
| root | % |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+---------------+-----------+
5 rows in set (0.00 sec)
- 更新資料庫,是配置生效
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
Master,Slave1的MySQL資料庫上建立CampusHire資料庫
- 進入Slave1執行相同1,2,3,4操作
配置主從資料庫連線
進入Master伺服器進行配置
- 進入mysql容器內部,修改配置檔案
docker exec -it mysql3306 bash
- 預設沒有vim,無法修改檔案
# 更新軟體源
apt update
# 安裝vim
apt install vim
- 修改mysql配置檔案
vim /etc/mysql/mysql.conf.d/mysqld.cnf
新增如下配置
#主從複製配置
innodb_flush_log_at_trx_commit=1
sync_binlog=1
#需要備份的資料庫
binlog-do-db=test
#不需要備份的資料庫
binlog-ignore-db=mysql
#啟動二進位制檔案
log-bin=mysql-bin
#伺服器ID
server-id=1
- 退出容器,重啟docker應用
docker restart mysql3306
- 進入資料庫,配置主從複製的許可權
mysql -h 127.0.0.1 -uroot -phello
mysql> grant replication slave on *.* to 'ninwoo'@'127.0.0.1' identified by 'hello';
Query OK, 0 rows affected, 1 warning (0.01 sec)
- 鎖定資料庫
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
- 檢視主資料庫資訊,記住下面的“File”與“Position”的資訊
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 439 | CampusHire | mysql | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
- 進入slave伺服器,進入mysql容器內部
# 更新軟體源
apt update
# 安裝vim
apt install vim
- 修改從資料庫的配置檔案
vim /etc/mysql/mysql.conf.d/mysqld.cnf
新增server-id=2
- 重啟Slave資料庫
docker restart mysql3306
- 進入資料庫,輸入剛剛記錄下來的File和Position
MySQL [(none)]> change master to master_host='10.0.0.1',
->
-> master_user='ninwoo',
-> master_password='hello',
-> master_port=3306,
-> master_log_file='mysql-bin.000001',
-> master_log_pos=439,
-> master_connect_retry=10;
- 啟動Slave程序
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
- 檢視複製狀態
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 139.199.194.49
Master_User: ninwoo
Master_Port: 3306
Connect_Retry: 10
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 439
Relay_Log_File: 2a8a4abdcf68-relay-bin.000002
Relay_Log_Pos: 320
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: 439
Relay_Log_Space: 534
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: 1
Master_UUID: 4a0187fa-b0a5-11e8-a7e7-0242ac110003
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more up dates
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: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
到這裡主從資料的配置就已經完成,在向主庫寫入資料的同時,將在從庫進行自動的備份。但在實際測試中遇到了配置完成之後無法向主資料庫寫入的問題,初步 判斷是由於主庫加鎖而未解鎖的問題,所以這裡採用比較暴力的方法,重啟主資料庫容器。
# master節點
docker restart mysql3306
配置Atlas
Atlas是有360團隊優化mysqlproxy而衍生出的版本,效能更好更穩定。
Atlas有兩個版本,這裡我選擇普通版本,即不分表。
在阿里雲主機(centos7)上進行一下安裝步驟:
- 下載安裝
[[email protected] ~]# cd /home/
[[email protected] home]# wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
- 安裝
[[email protected] home]# rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
安裝目錄位於/usr/local/mysql-proxy/
- 使用安裝目錄下的
bin/encrypt
程式加密資料庫密碼
[[email protected] bin]# ./encrypt hello
- 配置Atlas
[[email protected] conf]# cd /usr/local/mysql-proxy/conf/
[[email protected] conf]# vim test.cnf
修改以下配置:
#管理介面的使用者名稱
admin-username = user
#管理介面的密碼
admin-password = pwd
...
#Atlas後端連線的MySQL主庫的IP和埠,可設定多項,用逗號分隔
proxy-backend-addresses = 10.0.0.1:3306
#Atlas後端連線的MySQL從庫的IP和埠,@後面的數字代表權重,用來作負載均衡,若省略則預設為1,可設定多項,用逗號分隔
proxy-read-only-backend-addresses = 10.0.0.2:[email protected]
...
#使用者名稱與其對應的加密過的MySQL密碼,密碼使用PREFIX/bin目錄下的加密程式encrypt加密,下行的user1和user2為示例,將其替換為你的MySQL的使用者名稱和加密密碼!
pwds = buck:RePBqJ+5gI4=
...
#Atlas監聽的工作介面IP和埠
proxy-address = 0.0.0.0:1234
#Atlas監聽的管理介面IP和埠
admin-address = 0.0.0.0:2345
讀者需要根據自己的實際情況修改以上配置
- 啟動Atlas
[[email protected] bin]# /etc/init.d/mysqld status
OK: MySQL-Proxy of test is started
- 使用mysql命令連線資料庫
其中2345埠是管理埠,使用者可以在該管理資料庫中修改資料庫代理伺服器的相關配置
[[email protected] bin]# mysql -h127.0.0.1 -P2345 -uuser -ppwd
其中1234埠是資料庫代理伺服器的埠,使用者可以直接訪問該埠進行資料庫的訪問和更新
[[email protected] bin]# mysql -h127.0.0.1 -P1234 -ubuck -phello
- 使用軟體連線Atlas資料庫代理伺服器
這裡發現,之前使用的mysql workbench無法正常使用,更換Navicat可以正常使用。
- 使用jdbc連線資料庫
使用方法與普通資料庫一樣。
後記
到這裡,配置就已經全部完成。有心的讀者或者已經發現,還有一臺伺服器未使用,這臺伺服器將在以後接入到現有的mysql資料庫叢集當中,充當新的slave節點。該實驗將在以後補上。
理論上說,我所做的這些或許會對負載過大的問題有所解決。但最近並未出現太高的訪問現象,所以短期也沒有看到效果。具體效果,將在實際場景中驗證後補充上,敬請期待。