Mysql讀寫分離——主從數據庫+Atlas


mysql集群

最近在參加項目開發微信小程序后台,由於用戶數量巨大,且后台程序並不是很完美,所以對用戶的體驗很是不友好(簡單說就是很卡)。趕巧最近正在翻閱《大型網站系統與Java中間件實踐》。
所以,先是使用Docker swarm構建了負載均衡集群,然后使用Atlas做了數據庫的讀寫分離,盡可能對用戶進行分流,降低對單機服務器的負載,提高訪問體驗。本片隨筆僅對數據庫的讀寫分離部分進行介紹。

目標:實現mysql數據庫集群,一個主節點負責寫入數據,多個從節點負責讀取數據

實驗環境

服務器:

  1. 阿里雲服務器:centos7(10.0.0.1)
  2. 騰訊雲服務器:ubuntu:16.04(10.0.0.2)
  3. 京東雲服務器:ubuntu:16.04 (10.0.0.3)

mysql:5.7

docker:18.03

實現方案

mysql 主從數據庫 + Atlas讀寫分離

步驟:

進入Master服務器進行配置

  1. 使用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
  1. 進Master服務器的MySQL數據庫中,創建用戶"niwoo"設置密碼為"hello"
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)

  1. 修改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

  1. 確認是否修改成功
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)

  1. 更新數據庫,是配置生效
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

Master,Slave1的MySQL數據庫上創建CampusHire數據庫

  1. 進入Slave1執行相同1,2,3,4操作

配置主從數據庫連接

進入Master服務器進行配置

  1. 進入mysql容器內部,修改配置文件
docker exec -it mysql3306 bash
  1. 默認沒有vim,無法修改文件
# 更新軟件源
apt update
# 安裝vim
apt install vim
  1. 修改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 
  1. 退出容器,重啟docker應用
docker restart mysql3306
  1. 進入數據庫,配置主從復制的權限
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)

  1. 鎖定數據庫
mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)
  1. 查看主數據庫信息,記住下面的“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)
  1. 進入slave服務器,進入mysql容器內部
# 更新軟件源
apt update
# 安裝vim
apt install vim
  1. 修改從數據庫的配置文件
vim /etc/mysql/mysql.conf.d/mysqld.cnf

添加server-id=2

  1. 重啟Slave數據庫
docker restart mysql3306
  1. 進入數據庫,輸入剛剛記錄下來的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;
  1. 啟動Slave進程
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
  1. 查看復制狀態
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)上進行一下安裝步驟:

  1. 下載安裝
[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
  1. 安裝
[root@localhost home]# rpm -ivh Atlas-2.2.1.el6.x86_64.rpm 

安裝目錄位於/usr/local/mysql-proxy/

  1. 使用安裝目錄下的bin/encrypt程序加密數據庫密碼
[root@localhost bin]# ./encrypt hello
  1. 配置Atlas
[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

讀者需要根據自己的實際情況修改以上配置

  1. 啟動Atlas
[root@localhost bin]# /etc/init.d/mysqld status
OK: MySQL-Proxy of test is started
  1. 使用mysql命令連接數據庫

其中2345端口是管理端口,用戶可以在該管理數據庫中修改數據庫代理服務器的相關配置

[root@localhost bin]# mysql -h127.0.0.1 -P2345 -uuser -ppwd

其中1234端口是數據庫代理服務器的端口,用戶可以直接訪問該端口進行數據庫的訪問和更新

[root@localhost bin]# mysql -h127.0.0.1 -P1234 -ubuck -phello
  1. 使用軟件連接Atlas數據庫代理服務器

這里發現,之前使用的mysql workbench無法正常使用,更換Navicat可以正常使用。

  1. 使用jdbc連接數據庫

使用方法與普通數據庫一樣。

后記

到這里,配置就已經全部完成。有心的讀者或者已經發現,還有一台服務器未使用,這台服務器將在以后接入到現有的mysql數據庫集群當中,充當新的slave節點。該實驗將在以后補上。

理論上說,我所做的這些或許會對負載過大的問題有所解決。但最近並未出現太高的訪問現象,所以短期也沒有看到效果。具體效果,將在實際場景中驗證后補充上,敬請期待。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM