docker+atlas+mysql實現讀寫分離

聰明的大羊發表於2020-11-08

1、引言

引言:在大資料量,高併發等場景下,對資料庫壓力越來越大,通過優化sql,合理索引,分庫分表等措施已經無法滿足資料處理、儲存要求,因此通過代理和新增節點實現資料庫主從複製、讀寫分離提升效能是很好的一個選擇。網上關於atlas實現資料庫讀寫分離的文章少之又少,而且雷同,沒有詳細的執行步驟和結果,本文儘可能詳細介紹。

環境:Mac 、Docker version 19.03.13

2、準備

1、Docker

1、why Docker

菜鳥教程:Docker 是一個開源的應用容器引擎,基於 Go 語言並遵從 Apache2.0 協議開源。Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中,然後釋出到任何流行的 Linux 機器上,也可以實現虛擬化。容器是完全使用沙箱機制,相互之間不會有任何介面(類似 iPhone 的 app),更重要的是容器效能開銷極低。

簡單來說,docker映象拉取、部署非常方便,對本機檔案不會造成影響,輕量級,簡易部署,可以通過遠端api介面建立和管理容器。

2、Docker安裝

本文暫不介紹docker安裝,linux和mac安裝較為簡單,windows安裝稍微麻煩,要分清家庭版還是專業版,需要下載不同的Desktop版,踩過坑…

2、mysql主從複製

1、概述

實現讀寫分離的前提是主從複製,首先我們先完成搭建mysql資料庫的主從複製,這裡選擇兩個節點,一主一從。

參考:連結

2、搭建步驟

  • 檢查Docker
docker -v
#Docker version 19.03.13, build xxx
  • 拉取mysql映象
docker pull mysql:5.7
  • 建立master容器
docker run -p 3339:3306 --name mymysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
#3339:3306 將docker容器的3306埠對映到本地的3399埠,要非常注意,尤其是在之後的配置!!
#–name 給容器命名,mymysql;
#-d 表示容器在後臺執行,後面跟映象名稱
  • 建立slave容器
docker run -p 3340:3306 --name mymysql-slave -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
  • 檢視容器執行
docker ps 
#成功會輸出兩個正在執行的mysql容器資訊,分別為mymysql和mymysql-slave
  • 檢視兩個容器的ip
docker inspect --format='{{.NetworkSettings.IPAddress}}' mymysql
#172.17.0.2
docker inspect --format='{{.NetworkSettings.IPAddress}}' mymysql-slave
#172.17.0.3
  • 進入到容器裡面,開始mysql配置
docker exec -it mymysql /bin/bash
  • 安裝vim
apt-get update
apt-get install vim
  • 進入/etc/mysql,編輯my.cnf,新增以下內容儲存退出
[mysqld]
server-id=1
log-bin=mysql-bin
  • 重啟服務,重新啟動容器
service mysql restart
docker start mymysql
  • 同樣步驟配置slave
[mysqld]
## 設定server_id,注意要唯一
server-id=2
## 開啟二進位制日誌功能,以備Slave作為其它Slave的Master時使用
log-bin=mysql-slave-bin   
## relay_log配置中繼日誌
relay_log=edu-mysql-relay-bin 
  • 進入master容器內,啟動mysql,鍵入密碼123456
mysql -uroot -p
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
show master status;

file和position,這兩個值等會在配置slave的時候需要用到

  • 退出,進入到slave庫的mysql互動環境
change master to master_host='172.17.0.2', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000002', master_log_pos= 154, master_connect_retry=60;

注意master_log_file和master_log_pos要與上面master的一樣,配置中出了問題,重新啟動了也要重新看一下,一定要保持一致!

配置項內容:

master_log_file就是我們master當前使用的binlog檔名,就是上圖中的file名
master_log_pos=154 ,就是值記錄最大位置
新建的時候master的binlog檔名可能是mysql-bin.000001,照著裡面寫就好了
master_host :Master的地址,指的是容器的獨立ip
master_port:Master的埠號,指的是容器的埠號
master_user:用於資料同步的使用者
master_password:用於同步的使用者的密碼
master_log_file:指定 Slave 從哪個日誌檔案開始複製資料,即上文中提到的 File 欄位的值
master_log_pos:從哪個 Position 開始讀,即上文中提到的 Position 欄位的值
master_connect_retry:如果連線失敗,重試的時間間隔,單位是秒,預設是60秒
  • 在Slave 中的mysql終端執行
show slave status \G;
結果
 Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.17.0.2
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 2295
               Relay_Log_File: edu-mysql-relay-bin.000003
                Relay_Log_Pos: 611
        Relay_Master_Log_File: mysql-bin.000001
            Slave_IO_Running: No
            Slave_SQL_Running: No

Slave_IO_Running: No
Slave_SQL_Running: N0

開始是兩個no,這是正常情況,因為主從複製還未開始,
現在我們使用,啟動主從備份

start slave;

此時應該就是兩個yes了!

3、檢測

1、在主庫內新建資料庫並插入資料,發現從庫也有了對應內容

2、在本地用navicat連結一下主庫從庫,注意ip地址是查詢得到的,埠號是對外對映的埠號!!如果這一步能成功,才可以繼續做之後的Atlas代理讀寫分離,個人由於配置在此踩坑最終導致從頭再來。

3、讀寫分離

1、前提

已經搭建好可以對外服務的mysql主從複製叢集。

參考:連結

2、搭建步驟

  • 拉取Atlas映象
docker run -it --name atlas -v /usr/local/mysql-proxy/conf:/usr/local/mysql-proxy/conf -p 1234:1234 -p 2345:2345  mybbcat/docker-360atlas /bin/bash
  • 進入/usr/local/mysql-proxy/conf修改test.cnf
[mysql-proxy]

#帶#號的為非必需的配置專案

#管理介面的使用者名稱
admin-username = root

#管理介面的密碼
admin-password = 123456

#Atlas後端連線的MySQL主庫的IP和埠,可設定多項,用逗號分隔
proxy-backend-addresses = 172.17.0.2:3306

#Atlas後端連線的MySQL從庫的IP和埠,@後面的數字代表權重,用來作負載均衡,若省略則預設為1,可設定多項,用逗號分隔
proxy-read-only-backend-addresses = 172.17.0.3:3306

#使用者名稱與其對應的加密過的MySQL密碼,密碼使用PREFIX/bin目錄下的加密程式encrypt加密
pwds = root:DAJnl8cVzy8=

#設定Atlas的執行方式,設為true時為守護程式方式,設為false時為前臺方式,一般開發除錯時設為false,線上執行時設為true,true後面不能有空格。
daemon = true

#設定Atlas的執行方式,設為true時Atlas會啟動兩個程式,一個為monitor,一個為worker,monitor在worker意外退出後會自動將其重啟,設為false時只有worker,沒有monitor,一般開發除錯時設為false,線上執行時設為true,true後面不能有空格。
keepalive = true

#工作執行緒數,對Atlas的效能有很大影響,可根據情況適當設定
event-threads = 8

#日誌級別,分為message、warning、critical、error、debug五個級別
log-level = message

#日誌存放的路徑
log-path = /usr/local/mysql-proxy/log

#SQL日誌的開關,可設定為OFF、ON、REALTIME,OFF代表不記錄SQL日誌,ON代表記錄SQL日誌,REALTIME代表記錄SQL日誌且實時寫入磁碟,預設為OFF
sql-log = REALTIME

#慢日誌輸出設定。當設定了該引數時,則日誌只輸出執行時間超過sql-log-slow(單位:ms)的日誌記錄。不設定該引數則輸出全部日誌。
#sql-log-slow = 10

#例項名稱,用於同一臺機器上多個Atlas例項間的區分
instance = test

#Atlas監聽的工作介面IP和埠
proxy-address = 0.0.0.0:1234

#Atlas監聽的管理介面IP和埠
admin-address = 0.0.0.0:2345

#分表設定,此例中person為庫名,mt為表名,id為分表欄位,3為子表數量,可設定多項,以逗號分隔,若不分表則不需要設定該項
#tables = person.mt.id.3

#預設字符集,設定該項後客戶端不再需要執行SET NAMES語句
charset = utf8

#允許連線Atlas的客戶端的IP,可以是精確IP,也可以是IP段,以逗號分隔,若不設定該項則允許所有IP連線,否則只允許列表中的IP連線
#client-ips = 127.0.0.1, 192.168.1

#Atlas前面掛接的LVS的物理網路卡的IP(注意不是虛IP),若有LVS且設定了client-ips則此項必須設定,否則可以不設定
#lvs-ips = 192.168.1.1
  • 進入容器、
docker exec -it atlas /bin/bash
  • 進入/usr/local/mysql-proxy/bin目錄,執行下面的命令啟動、重啟或停止atlas
./mysql-proxyd test start      #啟動Atlas。
./mysql-proxyd test restart    #重啟Atlas。
./mysql-proxyd test stop       #停止Atlas。

說明

1、master、slave的ip地址和埠號是一個大坑,我配置成了對映埠,導致Atlas測試連結可以成功,但是一直報2013錯誤,修改為3306埠就正確了!

2、密碼加密,PREFIX/bin目錄,就是Atlasl的安裝目錄:/usr/local/mysql-proxy/bin 執行 ./encrypt ‘123456’

3、測試

1、使用Navicat連結atlas,使用對應的ip和對映的埠號,本文是1234,如果連結成功,執行建立資料庫和運算元據,觀察master和slave節點的變化,如果同步變化則搭建成功,如果失敗,檢查搭建環境的正確性

2、執行 tail -f /usr/local/mysql-proxy/log/sql_test.log驗證檢視讀和寫的操作是否正確

4、思考

  • 為什麼要主從複製:
    • 當主資料庫出現問題時,可以當從資料庫代替主資料庫,可以避免資料的丟失。
    • 可以進行讀寫分離
  • 為什麼要讀寫分離:
    • 避免從資料庫進行寫操作而導致的主從資料庫資料不一致的情況,因為當主從資料庫資料不一致時,那麼從資料庫最主要的備份任務就沒有意義了。
    • 減輕主資料庫的壓力。因為進行寫操作更耗時,所以如果不進行讀寫分離的話,寫操作將會影響到讀操作的效率。
  • Atlas:
    • 主要功能:讀寫分離、從庫負載均衡、.IP過濾、自動分表、DBA可平滑上下線DB、自動摘除當機的DB
    • 相對於官方MySQL-Proxy的優勢:將主流程中所有Lua程式碼用C重寫,Lua僅用於管理介面、重寫網路模型、執行緒模型、實現了真正意義上的連線池、.優化了鎖機制,效能提高數十倍
  • PHP是如何與Mysql互動的?

相關文章