最近在參加項目開發微信小程序後臺,因爲用戶數量巨大,且後臺程序並非很完美,因此對用戶的體驗非常不友好(簡單說就是很卡)。趕巧最近正在翻閱《大型網站系統與Java中間件實踐》。
因此,先是使用Docker swarm構建了負載均衡集羣,而後使用Atlas作了數據庫的讀寫分離,儘量對用戶進行分流,下降對單機服務器的負載,提升訪問體驗。本片隨筆僅對數據庫的讀寫分離部分進行介紹。mysql
目標:實現mysql數據庫集羣,一個主節點負責寫入數據,多個從節點負責讀取數據git
服務器:github
mysql:5.7sql
docker:18.03docker
mysql 主從數據庫 + Atlas讀寫分離數據庫
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
mysql -h 127.0.0.1 -uroot -phello mysql> grant all on *.* to ninwoo@'127.0.0.1' identified by "hello"; Query OK, 0 rows affected, 1 warning (0.00 sec)
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數據庫ubuntu
進入Master服務器進行配置小程序
docker exec -it mysql3306 bash
# 更新軟件源 apt update # 安裝vim apt install vim
vim /etc/mysql/mysql.conf.d/mysqld.cnf
添加以下配置vim
#主從複製配置 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 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)
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)
# 更新軟件源 apt update # 安裝vim apt install vim
vim /etc/mysql/mysql.conf.d/mysqld.cnf
添加server-id=2
後端
docker restart mysql3306
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;
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是有360團隊優化mysqlproxy而衍生出的版本,性能更好更穩定。
Atlas有兩個版本,這裏我選擇普通版本,即不分表。
在阿里雲主機(centos7)上進行一下安裝步驟:
[root@localhost ~]# cd /home/ [root@localhost home]# wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm
[root@localhost home]# rpm -ivh Atlas-2.2.1.el6.x86_64.rpm
安裝目錄位於/usr/local/mysql-proxy/
bin/encrypt
程序加密數據庫密碼[root@localhost bin]# ./encrypt hello
[root@localhost conf]# cd /usr/local/mysql-proxy/conf/ [root@localhost 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:3306@1 ... #用戶名與其對應的加密過的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
讀者須要根據本身的實際狀況修改以上配置
[root@localhost bin]# /etc/init.d/mysqld status OK: MySQL-Proxy of test is started
其中2345端口是管理端口,用戶能夠在該管理數據庫中修改數據庫代理服務器的相關配置
[root@localhost bin]# mysql -h127.0.0.1 -P2345 -uuser -ppwd
其中1234端口是數據庫代理服務器的端口,用戶能夠直接訪問該端口進行數據庫的訪問和更新
[root@localhost bin]# mysql -h127.0.0.1 -P1234 -ubuck -phello
這裏發現,以前使用的mysql workbench沒法正常使用,更換Navicat能夠正常使用。
使用方法與普通數據庫同樣。
到這裏,配置就已經所有完成。有心的讀者或者已經發現,還有一臺服務器未使用,這臺服務器將在之後接入到現有的mysql數據庫集羣當中,充當新的slave節點。該實驗將在之後補上。
理論上說,我所作的這些或許會對負載過大的問題有所解決。但最近並未出現過高的訪問現象,因此短時間也沒有看到效果。具體效果,將在實際場景中驗證後補充上,敬請期待。