整個事件的起源還要從筆者最近入職了一家區塊鏈金融公司來講起(爲了保密性,不便透露公司名字),公司業務發展比較迅猛,突破百萬用戶也是近在眼前。整個系統都在阿里雲上運行,天天都能看到用戶的不斷增加,即興奮又擔心,爲何這麼說呢?php
因爲筆者過來的時候這裏業務就已經上線了,系統接過來以後,快速瞭解了全部的應用服務都是在docker swarm跑起來的,也包括mysql數據庫,以致於筆者就有了遷庫的想法,按照這種用戶量發展下去,mysql在容器中運行用不了多久確定會撐不住。html
筆者就開始隱隱的擔心起來,畢竟不想天天提心吊膽的作運維。因此立馬從新規劃了新的方案和你們一塊兒探討,最終總監和相關技術負責人都敲定用RDS作爲數據庫新的方案,周星馳的功夫中也說道過:「天下武功,惟快不破」。就立馬開始動身幹起來。mysql
一、從入口層(CDN)---> 到安全層(WAF) ---> 最後到達應用層 (ECS集羣);
二、Docker Swarm打通了ECS集羣中的每臺服務器,在每臺ECS宿主機安裝Docker engine並部署了公司須要的應用服務和數據庫(nginx、php、redis、mysql等);
三、mysql容器經過宿主機的本地(目錄)掛載到容器中實現數據持久化;
四、業務項目以php爲主,php也是運行在容器中,經過php指定的配置文件鏈接到mysql容器中。nginx
筆者就隨便展現一下其中一個庫的yaml文件,比較簡單:redis
version: "3" services: ussbao: # replace username/repo:tag with your name and image details image: 隱藏此鏡像信息 deploy: replicas: 1 restart_policy: condition: on-failure environment: MYSQL_ROOT_PASSWORD: 隱藏此信息 volumes: - "/data//mysql/db1/:/var/lib/mysql/" - "/etc/localtime:/etc/localtime" - "/etc/timezone:/etc/timezone" networks: default: external: name: 隱藏此信息
從上面的信息能夠看出來,每一個庫只運行了一個mysql容器,並無主從或讀寫分離的方案。並且也沒有對數據庫進行作任何優化,數據庫這樣跑下去讓筆者很擔心,正常來講,都會把數據庫獨立部署運行。sql
從上圖能夠看出來,筆者只是把mysql獨立出來了,開通RDS實例來跑數據庫,固然還開通了其它的一些服務(好比oss、雲redis等),這些不是本文的重點,就沒有畫出來。nginx和php服務仍是在docker swarm中運行。本文只是對遷移後出了問題的庫進行分享,下面來看看遷移的方案吧。docker
開通RDS實例 ---> 備份sql ----> 導入到RDS ---> 修改數據庫配置文件 --->測試驗證數據庫
一、根據業務量規劃開通RDS實例,建立數據庫和用戶;
二、提早作好RDS白名單,添加容許訪問RDS的IP地址;
三、mysqldump 備份docker 中的mysql;
四、把備份好的.sql文件導入到RDS中;
五、修改php項目的數據庫配置文件;
六、清空php項目的緩存文件或目錄;
七、測試驗證;
八、RDS定時備份;緩存
具體遷移細節就不展現了,筆者是在夜深人靜的時候進行遷移操做的,肯定大半夜沒人訪問咱們的APP和網站了纔開乾的。安全
咱們的業務狀況還有點像股市,咱們是晚上12點不準操做和交易,第2天早上9點開盤,9點鐘是併發的高峯期,就像朝陽大悅城上午開門同樣,大批的顧客同時併發過來了。
因此那天晚上在12點15分準時開幹,按計劃和提早準備的配置、命令、腳本進行操做的。把docker 中運行的mysql遷移到RDS上很是順利,好幾個庫遷移不到半個小時就結束了,而且把網站和APP的流程都跑了一遍,也都是妥妥的,最終把提早準備好備份腳本放在crontab中定時執行,能夠來看下腳本內容:
#!/bin/bash #數據庫IP dbserver='*******' #數據庫用戶名 dbuser='ganbing' #數據庫密碼 dbpasswd='************' #備份數據庫,多個庫用空格隔開 dbname='db1 db2 db3' #備份時間 backtime=`date +%Y%m%d%H%M` out_time=`date +%Y%m%d%H%M%S` #備份輸出路徑 backpath='/data/backup/mysql/' logpath=''/data/backup/logs/' echo "################## ${backtime} #############################" echo "開始備份" #日誌記錄頭部 echo "" >> ${logpath}/${dbname}_back.log echo "-------------------------------------------------" >> ${logpath}/${dbname}_back.log echo "備份時間爲${backtime},備份數據庫 ${dbname} 開始" >> ${logpath}/${dbname}_back.log #正式備份數據庫 for DB in $dbname; do source=`/usr/bin/mysqldump -h ${dbserver} -u ${dbuser} -p${dbpasswd} ${DB} > ${backpath}/${DB}-${out_time}.sql` 2>> ${backpath}/mysqlback.log; #備份成功如下操做 if [ "$?" == 0 ];then cd $backpath #爲節約硬盤空間,將數據庫壓縮 tar zcf ${DB}-${backtime}.tar.gz ${DB}-${backtime}.sql > /dev/null #刪除原始文件,只留壓縮後文件 rm -f ${DB}-${backtime}.sql #刪除15天前備份,也就是隻保存15天內的備份 find $backpath -name "*.tar.gz" -type f -mtime +15 -exec rm -rf {} \; > /dev/null 2>&1 echo "數據庫 ${dbname} 備份成功!!" >> ${logpath}/${dbname}_back.log else #備份失敗則進行如下操做 echo "數據庫 ${dbname} 備份失敗!!" >> ${logpath}/${dbname}_back.log fi done echo "完成備份" echo "################## ${backtime} #############################"
到了1點鐘,肯定沒問題後發通知到羣裏,發微信給領導表示已遷移完成,進行很順利,而後筆者打車回家,睡覺。
其實這一晚筆者睡得也不踏實,到了8點半就醒了,由於咱們9點鐘開盤,會有大量的客戶涌進,天天開始產生新的交易(買入和賣出),給你們看下截圖:
果不其然,9點事後,筆者打開APP,一切正常,點擊切換幾個界面後,發現其中一個功能的請求超時了,一直在轉,而後緊接着其它功能也超時了。完了,出問題了。趕忙開筆記本查問題,過了一下子羣裏就開始沸騰了(反映好多客戶打開APP都顯示請求超時了),個人電話也立馬響了,技術總監打來的,問我怎麼回事,我說正在開筆記本排查。
這個時候,我要說明一下:運維人員此時須要冷靜而且安靜的處理問題,公司領導千萬別催得太急以避免打亂處理人的思路。咱們總監臨場處理能力作得真是很是到位,立刻跟我說不用擔憂上面壓力,有他扛着,叫我只管排查和解決問題。
筆記本打開後,首先想到的就是RDS數據庫出了問題,登陸阿里雲,進入RDS中的DMS數據管理控制檯,一進去就傻眼了 「CPU爆了」,這麼多鏈接數,以下圖:
進入會話去看看,發現會話「炸鍋了」,發現幾百頁的select都擠在ub_user_calculate這個表中,這個表是數據量相對大一些,這張表目前有200多萬條數據:
![]
天然反應就是去查看此表的結構,發現此表沒有索引,被驚訝到了,居然沒有索引,這...... 而後筆者返回源數據庫查看這張表,也發現沒有索引,由此能夠肯定我導過來的這張表就是沒有建立索引,以下圖:
分析:當數據庫中出現訪問表的SQL沒建立索引致使全表掃描,若是表的數據量很大掃描大量的數據,執行效率過慢,佔用數據庫鏈接,鏈接數堆積很快達到數據庫的最大鏈接數設置,新的應用請求將會被拒絕致使故障發生。
趕忙把此事反應給開發負責人,代表問題根源找到了,會話鎖死了,由其中的一張表沒有索引而致使的,問詢問須要給哪幾個字段加索引。而後接着操做增長索引:
點擊保存後,發現建立索引的sql一直卡死着,,以下圖所示:
忽然想起來還有一堆會話在那裏,先kill 掉全部會話吧,否則索引確定建立不了,而後又發現會話根本殺不完,以下圖:
怎麼辦呢?會話殺不完...
沒辦法,先把訪問入口切斷吧,反正如今用戶訪問也超時,就毅然絕對先把域名停了,訪問入口給切斷了,而後在增長索引,索引加上了。
入口也斷了,索引也加上了,發現CPU還下去,以下圖:
爲了快速讓CPU降下去,重啓這個實例吧:
實例重啓完後,CPU下去了,會話也下去了:
開啓入口層的域名訪問吧,在次觀察如今的會話和CPU等況,以下圖:
這就對了,會話也正常了,通知領導業務恢復。。。
筆者後期補的一張圖:在來看一下服務器CPU狀況(遷移MYSQL後的狀況),明顯逐漸好轉。
參考:https://help.aliyun.com/document_detail/52274.html?spm=a2c4g.11174283.6.812.ZGPyBQ
一、這次故障雖然是表沒有索引形成的,可是筆者是有責任的,沒有挨個表檢查一下表的結構;
二、經過這次故障也能夠看出來開發在設計表的真的要很是的重視,注意細節;
三、還有就是以前在容器中運行的mysql也時不時的出現CPU瓶頸(好比CPU使用率偶爾會達到80%以上),筆者應該就要提早發現這些問題,完全排查找出問題所在緣由在進行遷庫的操做。
本章內容到此結束,喜歡個人文章,請點擊最上方右角處的《關注》!!!