集群的最主要瓶頸是:磁盤。當我們面臨集群作戰的時候,我們所希望的是即讀即得。可是面對大數據,讀取數據需要經過磁盤IO,這里可以把IO理解為水的管道。管道越大越強,我們對于T級的數據讀取就越快。所以IO的好壞,直接影響了集群對于數據的處理。
集群的瓶頸提出多種看法,其中網絡和磁盤io的爭議比較大。這里需要說明的是網絡是一種稀缺資源,而不是瓶頸。
對于磁盤IO:(磁盤IO:磁盤輸出輸出)
當我們面臨集群作戰的時候,我們所希望的是即讀即得??墒敲鎸Υ髷祿x取數據需要經過IO,這里可以把IO理解為水的管道。管道越大越強,我們對于T級的數據讀取就越快。所以IO的好壞,直接影響了集群對于數據的處理。
這里舉幾個例子,讓大家來參考一下。
案例一
自從使用阿里云以來,我們遇到了三次故障(一、二、三),這三次故障都與磁盤IO高有關。
第一次故障發生在跑zzk.cnblogs.com索引服務的云 服務器上,當時的Avg.Disk Read Queue Length高達200多;
第二次故障發生在跑images.cnblogs.com靜態文件的云服務器上,當時的Avg.Disk Read Queue Length在2左右(后來分析,對于圖片站點這樣的直接讀文件進行響應的應用,Disk Read Queue Length達到這個值會明顯影響響應速度);
第三次故障發生在跑數據庫服務的云服務器上,當時的Avg. Disk Write Queue Length達到4~5,造成很多的數據庫寫入操作超時。
(這里既提到“硬盤”,又提到“磁盤”,我們這樣界定的:在云服務器中看到的硬盤叫磁盤[虛擬出來的硬盤],在集群中的物理硬盤叫硬盤)
這三次的磁盤IO高都不是我們云服務器內的應用引起的,最直接的證據就是將云服務遷移至另一個集群之后,問題立即解決。也就是說云服務器的磁盤IO高是因 為它所在的集群的硬盤IO高。
集群的硬盤IO是集群內所有云服務器的磁盤IO的累加,集群的硬盤IO高是因為集群中某些云服務器的磁盤IO過高。而我們自 己的云服務器內的應用產生的磁盤IO在正常范圍,問題出在其他用戶的云服務器產生過多的磁盤IO,造成整個集群硬盤IO高,從而影響了我們。
為什么其他云服務器引起的硬盤IO問題會影響到我們?問題的根源就在于集群的硬盤IO被集群中的所有云服務器所共享,而且這種共享沒有被有效的限制、沒有 被有效的隔離,大家都在爭搶這個資源,同時爭搶的人太多,就會排長多。
而且對于每個云服務器來說,也不知道有多少臺云服務器在爭搶,從云服務器使用者的角 度根本無法躲開這個爭搶;就像在世博會期間,你起再早去排隊,也得排超長的隊。
如果每個云服務器使用的硬盤IO資源是被限制或隔離的,其他云服務器產生再 多的磁盤IO也不會影響到我們的云服務器;就像在一個小區,你一個人租了一套房子,其他的一套房子即使住了100人,也不會影響到你。
你可以買到CPU、內存、帶寬、硬盤空間,你卻買不到一心一意為你服務的硬盤IO,這就是當前阿里云虛擬化平臺設計時未考慮到的一個重要問題。
經過與阿里云技術人員的溝通,得知他們已經意識到這個問題,希望這個問題能早日得到解決。
—————————————————————————————————————————————
案例2
云計算之路-遷入阿里云后:20130314云服務器故障經過
首先向大家致歉,這次云服務器故障發現于17:30左右,18:30左右恢復正常,給大家帶來了麻煩,請大家諒解!
故障的原因是云服務器所在的集群負載過高,磁盤寫入性能急劇下降,造成很多數據庫寫入操作超時。后來恢復正常的解決方法是將云服務器遷移至另一個集群。
下面是故障發生的主要經過:
今天上午9:15左右一位園友通過郵件反饋在訪問園子時遇到502 Bad Gateway錯誤.
這是由阿里云負載均衡器返回的錯誤,Tegine是由阿里巴巴開發的開源Web服務器。我們猜測阿里云提供的負載均衡服務可能是通過Tegine反向代理實現的。
這個錯誤頁面表示負載均衡器檢測到負載均衡中的云服務器返回了無效的響應,比如500系列錯誤。
我們將這個情況通過工單反饋給了阿里云,得到的處理反饋是繼續觀察,可能是這位用戶的網絡線路的臨時問題導致。
由于我們在這個時間段沒遇到這個問題,也沒有其他用戶反饋這個問題,我們也認可了繼續觀察的處理方式。
(根據我們后來的分析,出現502 Bad Gateway錯誤可能是集群出現了瞬時負載高的情況)
下午17:20左右,我們自己也遇到了502 Bad Gateway錯誤,持續了大約1-2分鐘。見下圖:
出問題期間,我們趕緊登錄到兩臺云服務器查看情況,發現IIS并發連接數增長至原來的30多倍,而Bytes Send/sec為0,而且兩臺云服務器都是同樣的情況。我們當時推斷,這兩臺云服務器本身應該沒有問題,問題可能出在它們與數據庫服務器之間的網絡通 信。我們繼續將這個情況通過工單反饋給阿里云。
剛把工單填好,我們就接到園友的電話反饋說博客后臺不能發布文章,我們一測試,果然不能發布,報數據庫超時錯誤,見下圖:
但打開現有的文章速度很快,也就是說讀正常,寫有問題。趕緊登錄數據庫服務器通過性能監視器查看磁盤IO情況,果然磁盤寫入性能有問題,見下圖:
Avg. Disk Write Queue Length超過1就說明有問題了,現在平均已經到了4~5。進入阿里云網站上的管理控制臺一看,磁盤IO問題就更明顯了,見下圖:
繼續向阿里云反饋情況,得到的反饋是這臺云服務器IOPS太高了,見下圖:
于是,阿里云工作人員將這臺云服務器遷移至另一個集群,問題立刻解決。
—————————————————————————————————————————————-
案例三
14:17左右,我們看到了這條閃存。立即進入博客后臺測試,發現提交時會出現如下的錯誤:
"Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding."
這是數據庫寫入超時的錯誤,對這個錯誤信息我們記憶猶新。之前遇到過兩次(3月14日、4月2日),都是數據庫服務器所在的云服務器磁盤IO問題引起的。
登上云服務器,查看Windows性能監視器,發現日志文件所在的磁盤的IO監測數據Avg.Disk Write Queue Length平均值在5以上。性能監視器中這個值的縱坐標最高值是1,可想而知5是多么高的一個值。性能監視器中的走勢圖幾乎是一條直線。見下圖(最高值 竟然達到了20,真恐怖):
(為什么數據庫寫入超時會表現于日志文件所在的磁盤IO高?因為數據庫恢復模式用的是Full,對數據庫的數據寫入,會先在日志中進行寫入操作。)
這次問題與3月14日磁盤IO問題的表現是一樣的,所以我們斷定這次也是同樣的原因,是云服務器所在集群的磁盤IO負載高引起的。
14:19,我們向阿里云提交了工單,特地在標題中加了“緊急”;
14:23,阿里云客服回復說正在核實我們提交的問題;
14:31,阿里云客服回復說已反饋給相關部門檢查;
14:42,沒有阿里云客服的進一步消息,我們就回復說“如果短時間內解決不了,希望盡快進行集群遷移”(3月14日就是通過集群遷移解決這個問題的,阿里云的技術人員也說過對于集群負載高引起的磁盤IO問題,目前唯一的解決辦法就是集群遷移);
14:47,阿里云客服只回復說正在處理;
14:59,還是沒消息,我們心急如焚(40分鐘過去了,連個說法都沒有),在工單中說:“能不能先做集群遷移?”;
然后,接到阿里云客服的電話,說集群中其他云服務器占用的磁盤IO高影響了我們,他們正在處理。。。
過了會,阿里云客服又打電話過來說可能是我們云服務器中的系統或應用導致服務器磁盤寫入卡死,讓我們重啟一下云服務器。(這樣的考慮可能是因為這時集群的負載已經降下來,但我們的云服務器磁盤IO還是高。)
15:23左右,我們重啟了數據庫服務器,但問題依舊。
15:30,阿里云客服終于決定進行集群遷移(從提交工單到決定集群遷移耗時1小10分鐘)
15:45,完成集群遷移(上次遷移5分鐘不到,這次用了15分鐘,這也是阿里云客服所說的進行集群遷移所需的最長時間)
遷移之后,傻眼了,磁盤IO(Avg.Disk Write Queue Length)還是那么高!
為什么這次集群遷移不能像上次那樣立即解決問題?我們猜測有兩個可能的原因:
1、遷移后所在的集群磁盤IO負載依然高;
2、 云服務器上出現磁盤IO很高的這個分區放的都是數據庫日志文件,可能這個時間段日志寫入操作比平時頻繁(但暴增幾乎沒有可能)而且所有日志文件在同一個分 區,超過了云服務器磁盤IO的某個極限,造成磁盤IO性能驟降(可能性比較大,依據是云計算之路-入阿里云后:解決images.cnblogs.com 響應速度慢的詭異問題)。雖然之前使用物理服務器時,日志文件也是放在同一個分區,從未出現過這個問題,但現在云服務器的磁盤IO能力無法與物理服務器相 比,而且磁盤IO會被集群上其他云服務器爭搶(詳見云計算之路-遷入阿里云后:問題的根源——買到她的“人”,卻買不到她的“心”)。
不管是哪一個原因,要解決問題只有一招也是最后一招——減輕日志文件所在的磁盤分區的IO壓力。
怎么減壓呢?根據“遷入阿里云后的一些心得”一文中的“提高整體磁盤IO性能的小偏方”,另外購買一塊磁盤空間,然后將存放博文內容的數據庫CNBlogsText(大文本數據寫入,對磁盤IO產生的壓力很大)的日志文件移至獨立的磁盤分區。
在SQL Server中,無法在線完成將數據庫日志文件從一個磁盤分區移至另一個磁盤分區。需要先detach數據庫,然后將日志文件復制至目標分區,然后再attach這個數據庫;在attach時,將日志文件的位置修改為新的路徑。
于是,在別無選擇的情況下,我們CNBlogsText數據庫進行detach操作,并且選擇了drop connections,哪知在detach的過程中悲劇發生了,detach失敗了,錯誤是:
Transaction (Process ID 124) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
在 detach的過程中竟然發生了死鎖,然后“被犧牲”了。讓人困惑的是,不是drop connections嗎,怎么還會發生死鎖?可能drop connections是在detach操作正式開始前,在detach的過程中,還會發生數據庫寫入操作,這時的寫入操作引發了deadlock。為什 么偏偏要讓detach犧牲?不合情理。
detach失敗后,CNBlogsText數據庫就處于Single User狀態。繼續detach,同樣的錯誤,同樣的“被犧牲”。
于是,重啟了一下SQL Server服務。重啟之后,CNBlogsText數據庫的狀態變為了In Recovery。
這時時間已經到了16:45。
這樣的In Recovery狀態以前沒遇到過,不知如何處理,也不敢輕舉妄動。
過了一段時間,刷新了一下SQL Server的Databases列表,CNBlogsText數據庫又顯示為之前的Single User狀態。(原來重啟SQL Server之后,會自動先進入In Recovery狀態,再進入到Single User狀態)
針對Single User狀態問題,在工單中咨詢了阿里云客服,阿里云客服聯系了數據庫工程師,得到的建議是進行這樣的操作:alter database $db_name SET multi_user
于是,執行了這樣的SQL:
exec sp_dboption 'CNBlogsText', N'single', N'false'
出現錯誤提示:
Database 'CNBlogsText' is already open and can only have one user at a time.
Single User狀態依舊,出現這個錯誤可能是因為這個數據庫不斷地有寫入操作,搶占著Single User狀態下只允許唯一的數據庫連接。
(更新:后來從阿里云DBA那學習到解決這個問題的方法:
select spid from sys.sysprocesses where dbid=DB_ID('dbname'); --得到當前占用數據庫的進程id kill [spid] go alter login [username] disable --禁用新的訪問 go use cnblogstext go alter database cnblogstext set multi_user with rollback immediate go
)
當時的情形下,我們不夠冷靜,急著想完成detach操作。覺得屏蔽CNBlogsText數據庫的所有寫入操作可能需要禁止這臺服務器的所有數據庫連接,這樣會影響整站的正常訪問,所以沒從這個角度下手。
這時時間已經到了17:08。
我們也準備了最最后一招,假如實在detach不了,假如日志文件也出了問題,我們可以通過數據文件恢復這個數據庫。這個場景我們遇到過,也實際成功操作過,詳見:SQL Server 2005數據庫日志文件損壞的情況下如何恢復數據庫。所需的SQL語句如下:
use master alter database dbname set emergency declare @databasename varchar(255) set @databasename='dbname' exec sp_dboption @databasename, N'single', N'true' --將目標數據庫置為單用戶狀態 dbcc checkdb(@databasename,REPAIR_ALLOW_DATA_LOSS) dbcc checkdb(@databasename,REPAIR_REBUILD) exec sp_dboption @databasename, N'single', N'false'--將目標數據庫置為多用戶狀態
即使最最后一招也失敗了,我們在另外一臺云服務器上有備份,在異地也有備份,都有辦法恢復,只不過需要的恢復時間更長一些。
想到這些,內心平靜了一些,認識到當前最重要的是拋開內疚、緊張、著急,冷靜面對。
我們在工單中繼續咨詢阿里云客服,阿里云客服聯系了數據庫工程師,讓我們加一下這位工程師的阿里旺旺。
我們的電腦上沒裝阿里旺旺,于是打算自己再試試,如果還是解決不了,再求助阿里云的數據庫工程師。
在網上找了一個方法:SET DEADLOCK_PRIORITY NORMAL(來源),沒有效果。
時間已經到了17:38。
這時,我們冷靜地分析一下:detach時,因為死鎖“被犧牲”;從單用戶改為多用戶時,提示“Database 'CNBlogsText' is already open and can only have one user at a time.”??赡芏际且驗槌绦蛑胁粩嗟貙@個數據庫有寫入操作。試試修改一下程序,看看能不能屏蔽所有對這個數據庫的寫入操作,然后再將數據庫恢復為多 用戶狀態。
修改好程序,18:00之后進行了更新。沒想到更新之后,將單用戶改為多用戶的SQL就能執行了:
exec sp_dboption 'CNBlogsText', N'single', N'false'
于是,Single User狀態消失,CNBlogsText數據庫恢復了正常狀態,然后嘗試detach,一次成功。
接著將日志文件復制到新購的磁盤分區中,以新的日志路徑attach數據庫。attach成功之后,CNBlogsText數據庫恢復正常,博客后臺可以正常發布博文,CNBlogsText數據庫日志文件所在分區的磁盤IO(單獨的磁盤分區)也正常。問題就這么解決了。
當全部恢復正常,如釋重負的時候,時間已經到了18:35。
原以為可以用