2016年春節微信紅包巨大業務量,數據庫承受巨大負載html
mysql 集羣方案介紹,建議使用pxc,由於弱一致性會有問題,好比說a節點數據庫顯示我購買成功,b 節點數據庫顯示沒有成功,這就麻煩了,pxc 方案是在所有節點都寫入成功以後纔會告訴你成功,是可讀可寫雙向同步的,可是replication是單向的,不一樣節點的數據庫之間都會開放端口進行通信,若是從防火牆的這個端口關閉,pxc就不會同步成功,也不會返給你成功了。
java
Replicationnode
PXC (Percona XtraDB Cluster)mysql
建議PXC使用PerconaServer (MySQL改進版,性能提高很大)linux
PXC的數據強一致性nginx
在Docker中安裝PXC集羣,使用Docker倉庫中的PXC官方鏡像:https://hub.docker.com/r/percona/percona-xtradb-cluster算法
docker pull percona/percona-xtradb-cluster
或者本地安裝sql
docker load < /home/soft/pxc.tar.gz
安裝完成:docker
[root@localhost ~]# docker pull percona/percona-xtradb-cluster Using default tag: latest Trying to pull repository docker.io/percona/percona-xtradb-cluster ... latest: Pulling from docker.io/percona/percona-xtradb-cluster ff144d3c0ab1: Pull complete eafdff1524b5: Pull complete c281665399a2: Pull complete c27d896755b2: Pull complete c43c51f1cccf: Pull complete 6eb96f41c54d: Pull complete 4966940ec632: Pull complete 2bafadcea292: Pull complete 3c2c0e21b695: Pull complete 52a8c2e9228e: Pull complete f3f28eb1ce04: Pull complete d301ece75f56: Pull complete 3d24904bec3c: Pull complete 1053c2982c37: Pull complete Digest: sha256:17c64dacbb9b62bd0904b4ff80dd5973b2d2d931ede2474170cbd642601383bd Status: Downloaded newer image for docker.io/percona/percona-xtradb-cluster:latest [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/percona/percona-xtradb-cluster latest 70b3670450ef 2 months ago 408 MB
docker tag percona/percona-xtradb-cluster:latest pxc
而後原來的鏡像就能夠刪除掉了數據庫
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/percona/percona-xtradb-cluster latest 70b3670450ef 2 months ago 408 MB pxc latest 70b3670450ef 2 months ago 408 MB docker.io/java latest d23bdf5b1b1b 2 years ago 643 MB [root@localhost ~]# docker rmi docker.io/percona/percona-xtradb-cluster Untagged: docker.io/percona/percona-xtradb-cluster:latest Untagged: docker.io/percona/percona-xtradb-cluster@sha256:17c64dacbb9b62bd0904b4ff80dd5973b2d2d931ede2474170cbd642601383bd [root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE pxc latest 70b3670450ef 2 months ago 408 MB docker.io/java latest d23bdf5b1b1b 2 years ago 643 MB
# 建立網段 docker network create --subnet=172.18.0.0/24 net1 # 查看網段 docker network inspect net1 # 刪除網段 # docker network rm net1
# 建立名稱爲v1的數據卷,--name能夠省略
docker volume create --name v1
查看數據卷
docker inspect v1
結果:
[root@localhost ~]# docker inspect v1 [ { "Driver": "local", "Labels": {}, "Mountpoint": "/var/lib/docker/volumes/v1/_data",#這裏是在宿主機的保存位置 "Name": "v1", "Options": {}, "Scope": "local" } ]
刪除數據卷
docker volume rm v1
建立5個數據卷
# 建立5個數據卷 docker volume create --name v1 docker volume create --name v2 docker volume create --name v3 docker volume create --name v4 docker volume create --name v5
# 建立5個PXC容器構成集羣 # 第一個節點 docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql --name=node1 --network=net1 --ip 172.18.0.2 pxc # 在第一個節點啓動後要等待一段時間,等候mysql啓動完成。 # 第二個節點 docker run -d -p 3307:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v2:/var/lib/mysql --name=node2 --net=net1 --ip 172.18.0.3 pxc # 第三個節點 docker run -d -p 3308:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v3:/var/lib/mysql --name=node3 --net=net1 --ip 172.18.0.4 pxc # 第四個節點 docker run -d -p 3309:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v4:/var/lib/mysql --name=node4 --net=net1 --ip 172.18.0.5 pxc # 第五個節點 docker run -d -p 3310:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v5:/var/lib/mysql --name=node5 --net=net1 --ip 172.18.0.6 pxc
查看:
[root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f4708ce32209 pxc "/entrypoint.sh " About a minute ago Up About a minute 4567-4568/tcp, 0.0.0.0:3309->3306/tcp node4 bf612f9586bc pxc "/entrypoint.sh " 17 minutes ago Up 17 minutes 4567-4568/tcp, 0.0.0.0:3310->3306/tcp node5 9fdde5e6becd pxc "/entrypoint.sh " 17 minutes ago Up 17 minutes 4567-4568/tcp, 0.0.0.0:3308->3306/tcp node3 edd5794175b6 pxc "/entrypoint.sh " 18 minutes ago Up 18 minutes 4567-4568/tcp, 0.0.0.0:3307->3306/tcp node2 33d842de7f42 pxc "/entrypoint.sh " 21 minutes ago Up 21 minutes 0.0.0.0:3306->3306/tcp, 4567-4568/tcp node1
雖然搭建了集羣,可是不使用數據庫負載均衡,單節點處理全部請求,負載高,性能差
將請求均勻地發送給集羣中的每個節點。
負載均衡首先是數據庫的集羣,加入5個集羣,每次請求都是第一個的話,有可能第一個數據庫就掛掉了,因此更優的方案是對不一樣的節點都進行請求,這就須要有中間件進行轉發,比較好的中間件有nginx,haproxy等,因nginx 支持插件,可是剛剛支持了tcp/ip 協議,haproxy 是一個老牌的中間轉發件。若是要用haproxy的話,能夠從官方下載鏡像,而後呢對鏡像進行配置(本身寫好配置文件,由於這個鏡像是沒有配置文件的,配置好以後再運行鏡像的時候進行文件夾的映射,配置文件開放3306(數據庫請求,而後根據check心跳檢測訪問不一樣的數據庫,8888 對數據庫集羣進行監控))。配置文件裏面設置用戶(用戶在數據庫進行心跳檢測,判斷哪一個數據庫節點是空閒的,而後對空閒的進行訪問),還有各類算法(好比輪訓),最大鏈接數,時間等,還有對集羣的監控。配置文件寫好之後運行這個鏡像,鏡像運行成功後進入容器啓動配置文件 。其實haprocy返回的也是一個數據庫實例(可是並不存儲任何的數據,只是轉發請求),這個實例用來check其餘節點。
從Docker倉庫拉取haproxy鏡像:https://hub.docker.com/_/haproxy
docker pull haproxy
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/haproxy latest 11fa4d7ff427 11 days ago 72.2 MB
建立Haproxy配置文件。供Haproxy容器使用(docker中未生成配置文件,咱們須要在宿主機中本身建立配置文件)
配置文件詳情參考:http://www.javashuo.com/article/p-brcvyoqi-bb.html
# 啓動容器時使用目錄映射技術使容器讀取該配置文件
touch /home/soft/haproxy/haproxy.cfg
haproxy.cfg
# haproxy.cfg global #工做目錄 chroot /usr/local/etc/haproxy #日誌文件,使用rsyslog服務中local5日誌設備(/var/log/local5),等級info log 127.0.0.1 local5 info #守護進程運行 daemon defaults log global mode http #日誌格式 option httplog #日誌中不記錄負載均衡的心跳檢測記錄 option dontlognull #鏈接超時(毫秒) timeout connect 5000 #客戶端超時(毫秒) timeout client 50000 #服務器超時(毫秒) timeout server 50000 #監控界面 listen admin_stats #監控界面的訪問的IP和端口 bind 0.0.0.0:8888 #訪問協議 mode http #URI相對地址 stats uri /dbs #統計報告格式 stats realm Global\ statistics #登錄賬戶信息 stats auth admin:abc123456 #數據庫負載均衡 listen proxy-mysql #訪問的IP和端口 bind 0.0.0.0:3306 #網絡協議 mode tcp #負載均衡算法(輪詢算法) #輪詢算法:roundrobin #權重算法:static-rr #最少鏈接算法:leastconn #請求源IP算法:source balance roundrobin #日誌格式 option tcplog #在MySQL中建立一個沒有權限的haproxy用戶,密碼爲空。Haproxy使用這個帳戶對MySQL數據庫心跳檢測 option mysql-check user haproxy server MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000 server MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000 server MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000 server MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000 server MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000 #使用keepalive檢測死鏈 option tcpka
create user 'haproxy'@'%' identified by '';
# 這裏要加 --privileged docker run -it -d -p 4001:8888 -p 4002:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h1 --net=net1 --ip 172.18.0.7 --privileged haproxy
docker exec -it h1 bash
haproxy -f /usr/local/etc/haproxy/haproxy.cfg
這時候咱們手動掛掉一個Docker節點,看一下變化(咱們會發現已經顯示掛掉了)
單節點Haproxy不具有高可用,必需要有冗餘設計
雙機就是兩個請求處理程序,好比兩個haproxy,當一個掛掉的時候,另外 一個能夠頂上。熱備我理解就是keepalive。在haproxy 容器中安裝keepalive。
linux系統能夠在一個網卡中定義多個IP地址,把這些地址分配給多個應用程序,這些地址就是虛擬IP,Haproxy的雙機熱備方案最關鍵的技術就是虛擬IP。
關鍵就是虛擬ip,定義一個虛擬ip,而後好比兩個haproxy分別安裝keepalive鏡像,由於haproxy是ubuntu系統的,因此安裝用apt-get,keepalive是做用是搶佔虛擬ip,搶到的就是主服務器,沒有搶到的就是備用服務器,而後兩個keepalive進行心跳檢測(就是建立一個用戶到對方那裏試探,看是否還活着,mysql的集羣之間也是心跳檢測),若是 掛掉搶佔ip。因此在啓動keepalive 以前首先要編輯好他的配置文件,怎麼搶佔,權重是什麼,虛擬ip是什麼,建立的用戶交什麼。配置完啓動完之後能夠ping一下看是否正確,而後將虛擬ip映射到局域網的ip
$ docker exec -it h1 bash apt-get update apt-get install keepalived
# vim /etc/keepalived/keepalived.conf vrrp_instance VI_1 { state MASTER # Keepalived的身份(MASTER主服務要搶佔IP,BACKUP備服務器不會搶佔IP)。 interface eth0 # docker網卡設備,虛擬IP所在 virtual_router_id 51 # 虛擬路由標識,MASTER和BACKUP的虛擬路由標識必須一致。從0~255 priority 100 # MASTER權重要高於BACKUP數字越大優先級越高 advert_int 1 # MASTER和BACKUP節點同步檢查的時間間隔,單位爲秒,主備之間必須一致 authentication { # 主從服務器驗證方式。主備必須使用相同的密碼才能正常通訊 auth_type PASS auth_pass 123456 } virtual_ipaddress { # 虛擬IP。能夠設置多個虛擬IP地址,每行一個 172.18.0.201 } }
service keepalived start
建立Haproxy容器(name=h2的緣由是爲了高可用)
# 這裏要加 --privileged docker run -it -d -p 4003:8888 -p 4004:3306 -v /home/soft/haproxy:/usr/local/etc/haproxy --name h2 --net=net1 --ip 172.18.0.8 --privileged haproxy
進入容器
docker exec -it h2 bash
在容器bash中啓動Haproxy
haproxy -f /usr/local/etc/haproxy/haproxy.cfg
接下來即可以在瀏覽器中打開Haproxy監控界面,端口4003,在配置文件中定義有用戶名admin,密碼abc123456。
我這邊訪問的是http://192.168.63.144:4003/dbs,而且要使用用戶名密碼進行登陸(小插曲,使用的是Basic登陸,個人Chrome不知爲什麼被屏蔽了,我最後用的火狐)
apt-get update apt-get install keepalived
Keepalived配置文件(Keepalived.conf):
Keepalived的配置文件是/etc/keepalived/keepalived.conf
# vim /etc/keepalived/keepalived.conf vrrp_instance VI_1 { state MASTER # Keepalived的身份(MASTER主服務要搶佔IP,BACKUP備服務器不會搶佔IP)。 interface eth0 # docker網卡設備,虛擬IP所在 virtual_router_id 51 # 虛擬路由標識,MASTER和BACKUP的虛擬路由標識必須一致。從0~255 priority 100 # MASTER權重要高於BACKUP數字越大優先級越高 advert_int 1 # MASTER和BACKUP節點同步檢查的時間間隔,單位爲秒,主備之間必須一致 authentication { # 主從服務器驗證方式。主備必須使用相同的密碼才能正常通訊 auth_type PASS auth_pass 123456 } virtual_ipaddress { # 虛擬IP。能夠設置多個虛擬IP地址,每行一個 172.18.0.201 } }
啓動Keepalived
service keepalived start
啓動成功後,經過 ip a 能夠查看網卡中虛擬IP是否成功,另外能夠在宿主機中ping成功虛擬IP 172.18.0.201
查看當前局域網IP分配狀況:
yum install nmap -y nmap -sP 192.168.1.0/24
yum install keepalived
vrrp_instance VI_1 { state MASTER #這裏是宿主機的網卡,能夠經過ip a查看當前本身電腦上用的網卡名是哪一個 interface ens33 virtual_router_id 100 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { #這裏是指定的一個宿主機上的虛擬ip,必定要和宿主機網卡在同一個網段, #個人宿主機網卡ip是192.168.63.144,因此指定虛擬ip是160 192.168.63.160 } } #接受監聽數據來源的端口,網頁入口使用 virtual_server 192.168.63.160 8888 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP #把接受到的數據轉發給docker服務的網段及端口,因爲是發給docker服務,因此和docker服務數據要一致 real_server 172.18.0.201 8888 { weight 1 } } #接受數據庫數據端口,宿主機數據庫端口是3306,因此這裏也要和宿主機數據接受端口一致 virtual_server 192.168.63.160 3306 { delay_loop 3 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP #同理轉發數據庫給服務的端口和ip要求和docker服務中的數據一致 real_server 172.18.0.201 3306 { weight 1 } }
service keepalived start
#service keepalived status
#service keepalived stop
vi /etc/sysctl.conf #文件中添加net.ipv4.ip_forward=1這個配置 systemctl restart network
而後把虛擬機掛起
熱備份是在系統運行狀態下備份數據
MySQL常見的熱備份有LVM和XtraBackup兩種方案
XtraBackup是一款基於InnoDB的在線熱備工具,具備開源免費,支持在線熱備,佔用磁盤空間小,可以很是快速地備份與恢復mysql數據庫
docker volume create backup
挑選一個PXC節點node1,將其容器中止並刪除,而後從新建立一個增長了backup目錄映射的node1容器
docker stop node1 docker rm node1 # 數據庫數據保存在Docker卷v1中,不會丟失 # 參數改變: # 1. -e CLUSTER_JOIN=node2;原來其餘節點是經過node1加入集羣的,如今node1從新建立,須要選擇一個其餘節點加入集羣 # 2. -v backup:/data;將Docker卷backup映射到容器的/data目錄 docker run -d -u root -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node2 -v v1:/var/lib/mysql -v backup:/data --network=net1 --ip 172.18.0.2 --name=node1 pxc
在node1容器中安裝 percona-xtrabackup-24
docker exec -it node1 bash apt-get update apt-get install percona-xtrabackup-24
以後即可以執行以下命令進行全量備份,備份後的數據會保存在 /data/backup/full
目錄下:
mkdir /data/backup mkdir /data/backup/full #不建議,已過期 innobackupex --backup -u root -p abc123456 --target-dir=/data/backup/full xtrabackup --backup -uroot -pabc123456 --target-dir=/data/backup/full
官方文檔已經不推薦使用 innobackupex
,而推薦使用 xtrabackup
命令
數據庫能夠熱備份,可是不能熱還原,不然會形成業務數據和還原數據的衝突。
對於PXC集羣爲了不還原過程當中各節點數據同步衝突的問題,咱們要先解散原來的集羣,刪除節點。而後新建節點空白數據庫,執行還原,最後再創建起其餘集羣節點。
還原前還要將熱備份保存的未提交的事務回滾,還原以後重啓MySQL
docker stop node1 node2 node3 node4 node5
docker rm node1 node2 node3 node4 node5
docker volume rm v1 v2 v3 v4 v5
按照以前的步驟從新建立node1容器,並進入容器,執行冷還原
# 建立卷 docker volume create v1 # 建立容器 docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql -v backup:/data --name=node1 --network=net1 --ip 172.18.0.2 pxc # 以root身份進入容器 docker exec -it -uroot node1 bash # 刪除數據 rm -rf /var/lib/mysql/* # 準備階段 xtrabackup --prepare --target-dir=/data/backup/full/ # 執行冷還原 xtrabackup --copy-back --target-dir=/data/backup/full/ # 更改還原後的數據庫文件屬主 chown -R mysql:mysql /var/lib/mysql # 退出容器後,重啓容器 docker stop node1 docker start node1