可擴展性
直接連接
2.修改應用的配置
還有一個分發負載的辦法是重新配置應用。例如,你可以配置多個機器來分擔生成大報表操作的負載。每臺機器可以配置成連接到不同的MySQL備庫,并為第N個用戶或網站生成報表。
這樣的系統很容易實現,但如果需要修改一些代碼——包括配置文件修改——會變得脆弱且難以處理。硬編碼有著固有的限制,需要在每臺機器上修改硬編碼,或者在一個中心服務器上修改,然后通過文件副本或代碼控制更新命令"發布"到其他服務器上,如果將配置存儲在服務器或緩存中,就可以避免這些麻煩。
3.修改DNS名
這是一個比較粗糙的負載均衡技術,但對于一些簡單的應用,為不同的目的創建DNS還是很實用的。你可以為不同的服務器指定一個合適的名字。最簡單的方法是只讀服務器有一個NDS名,而給負責寫操作的服務器起另外一個DNS名。如果備庫能夠跟上主庫,那就把只讀DNS名指定給備庫,當出現延遲時,再將該DNS名指定給主庫。這種DNS技術非常容易實現,但也有很多缺點。最大的問題是無法完全控制DNS.
- 1.修改DNS并不是立刻生效的,也不是原子的。將DNS的變化傳遞到整個網絡或在網絡間傳播都需要比較長的時間
- 2.DNS數據會在各個地方緩存下來,它的過期時間是建議性質的,而非強制的
- 3.可能需要應用或服務器重啟才能使修改后的DNS完全生效。
- 4.多個IP共用一個DNS名依賴于輪詢行為來均衡請求,這并不是一個好主意,因為輪詢行為并不宗總是可預知的
- 5.DBA可能沒有權限直接訪問DNS
除非應用非常簡單,否則依賴不受控制的系統會非常危險。你可以通過修改/etc/hosts/文件而非DNS來改善對系統的控制。當發布一個對該文件的更新時,會知道該變更已經生效。這比等待緩存的DNS失效要好得多。但這仍然不是理想的辦法。通常建議人們構建一個完全不依賴DNS的應用。即使應用很簡單也適用,因為你無法預知應用會增長到多大規模。
4.轉移IP地址
一些負載均衡解決方案依賴于在服務器間轉移虛擬地址(虛擬IP地址不是直接連接到任何特定的計算機或網絡端口,而是"漂浮"在計算機之間),一般能夠很好地工作。這聽起來和修改DNS很像,但完全時兩碼事。服務器不會根據DNS名去監聽網絡流量,而是根據指定的IP地址去見挺流量,所以轉移IP地址允許DNS名保持不變。你可以通過ARP(地址解析協議)命令強制IP地址的更改快速而且原子性地通知到網絡上。看過的適用最普遍的技術時Pacemaker,這是Linux-HA享目的Heartbeat工具的繼承者。你可以適用單個IP地址,為其分配一個角色,例如read-only,當需要在機器間轉移IP地址時,它能夠感知到。其他的類似的工具包括LVS和Wackamole.
一個比較方便的技術時為每個物理服務器分配一個固定的IP地址。該IP地址固定在服務器上,不再改變。然后可以為每個邏輯上的"服務"使用一個虛擬IP地址。它們能夠很方便地在服務器間轉移,這使得轉移服務和應用實例無須再重新配置應用,因此更加容易。即使不怎么經常轉移IP地址,這也是一個很好地特性。
引入中間件
迄今為止,我們所討論的方案都嘉定應用跟MySQL服務器使直接相連的。但是許多負載均衡解決方案都會引入一個中間件,作為網絡通信的代理。它以便接受所有的通信請求,另一邊將這些請求派發到指定的服務器上,然后把執行結果發送回請求的機器上。中間件可以實硬件設備或時軟件(你可以把諸如LVS這樣的解決方案配置成只有一個用需要創建一個新連接時才參與進來,此后不再作為中間價)。如圖描述了這種架構,這種解決方案通常能工作得很好,當然除非為負載均衡器本身增加冗余,這樣才能避免單點故障引起的整個系統癱瘓。從開源軟件,如HAProxy,到許多廣為人知的商業系統,有許多負載均衡器得到了成功的應用
1.負載均衡器
在市場上有許多負載均衡硬件和軟件,但很少有專門為MySQL服務器設計的(MySQL Proxy是個例外,但目前還未能證明能夠很好地工作,因為它會帶來一些問題,例如延遲增加以及可擴展性瓶頸)。Web服務器通常更需要負載均衡,因此許多多用途的負載均衡設備都會支持HTTP,而對其他用途則只有一些很少的基本特性。MySQL連接都只是正常的TCP/IP連接,所以可以在MySQL上適用多用途負載均衡器。但由于缺少MySQL專有的特性,因此回多一些限制。
- 1.除非負載均衡器知道MySQL的真實負載,否則在分發請求時可能無法做到很好的負載均衡。不是所有的請求都是等同的,但多用途負載均衡器通常對所有的請求一視同仁。
- 2.許多負載均衡器知道如何檢查一個HTTP請求并把會話"固定"到一個服務器上以保護在Web服務器上的會話狀態。MySQL連接也是有狀態的,但負載均衡器可能并不知道如何把所有從單個HTTP會話發送的連接請求"固定"到一個MySQL服務器上,這回損失一部分效率(如果單個會話的請求都是發到同一個MySQL服務器,服務器的緩存會更優效率)
- 3.連接池和長連接可能會阻礙負載均衡器分發連接請求。例如,一個連接池打開了預先配置好的連接數,負載均衡器在已有的四個MySQL服務器上分發這些連接。現在增加了兩個以上的MySQL服務器。由于連接池不會請求新連接,因而新的服務器會一直空閑著。池中的連接會在服務器間不公平地分配負載,導致一些服務器超出負載,一些則幾乎沒有負載。可以在多個層面為連接設置失效時間來緩解這個問題,但這很復雜并且很難做到。連接池方案只有它們本身能夠處理負載均衡時才能工作得很好。
- 4.許多多用途負載均衡器只會針對HTTP服務器做健康和負載檢查。一個簡單的負載均衡器最少能夠核實服務器在一個TCP端口上接受的連接數。更好的負載均衡器能夠自動發起一個HTTP請求,并檢查返回值以確定這個Web服務器是否正常運轉。MySQL并不接受3306端口的HTTP,因此需要自己來構建健康檢查方法。你可以在MySQL服務器上安裝一個HTTP服務器如那件,并將負載均衡器指向一個腳本,這個腳本檢查MySQL服務器的狀態并返回一個對應的狀態值(實際上,如果能編碼實現一個監聽80端口的程序,或者配置xinetd來調用程序,甚至不需要再安裝一個Web服務器)。最重要的時檢查操作系統負載(通過查看/proc/loadavg)、復制狀態,以及MySQL的連接數。
2.負載均衡算法
有許都算法用來決定哪個服務器接受下一個連接。每個廠商都有各自不同的算法,下面這個清單列出了一些可用的方法:
- 1.隨機
負載均衡器隨機地從可用的服務器池中選擇一個服務器來處理請求 - 2.輪詢
負載均衡器以循環順序發送請求到服務器,例如:A,B,C,A,B,C - 3.最少連接數
下一個連接請求分配給擁有最少活躍連接的服務器 - 4.最快響應
能夠最快處理請求的服務器接受下一個連接。當服務器池里同時存在快速和慢速服務器時,這很有小。即使同樣的查詢在不同的場景下運行也會有不同的表現,例如當查詢結果已經緩存在查詢緩存中,或者服務器緩存中已經包含了所需要的數據時 - 5.哈希
負載均衡器通過連接的源IP地址進行哈希,將其映射到池中的同一個服務器上。每次從同一個IP地址發起請求,負載均衡器都會將請求發送給同樣的服務器。只有當池中服務器數目改變時這種綁定才會發生變化 - 6.權重
負載均衡器能夠結合適用上述幾種算法。例如,你可能擁有單CPU核雙CPU的機器。雙CPU機器有接近兩倍的性能,所以可以讓負載均衡器分派兩倍的請求給雙CPU機器
哪種算法最優取決于具體的工作負載。例如最少連接算法,如果有新機器加入,可能會有大量連接涌入該服務器,而這時候它的緩存還沒有包含熱數據。你需要通過測試來為你的工作負載找到最好的性能。除了正常的日常運轉,還需要考慮極端情況。在比較極端的情況下——例如負載升高,修改模式,或者多臺服務器下線——至少要避免系統出現重大錯誤。我們這里只描述了即時處理請求的算法,無須對連接請求排隊。但有時候適用排隊算法可能更有效。例如,一個算法可能只維護給定的數據庫服務器并發數目,同一時刻只允許不超過N個活躍事務。如果有太多的活躍事務,就將新的請求放到一個隊列里,然后讓可用服務器列表的第一個來處理它。有些連接池也支持隊列算法
3.在服務器池中增加/移除服務器
增加一個服務器到池中并不是簡單地插入禁區,然后通知負載均衡器就可以了,你可能以為只要不是一下子涌進大量連接請求就可以了,但并不一定如此。有時候你會緩慢增加一臺服務器的負載,但一些緩存還是"冷"的服務器可能會慢到一段時間內都無法處理任何的用戶請求。如果用戶瀏覽一個頁面需要30秒才能返回數據,即使流量很小,這個服務器也是不可用的。有一個方法可以避免這個問題,在通知負載均衡器有新服務器加入前,可以暫時把SELECT查詢映射到一臺活躍服務器上,然后再新開啟的服務器上讀取和重放活躍服務器上的日志文件,或者捕捉生產服務器上的網絡通信,并重放它的一部分查詢。Percona Toolkit中的pt-query-digest工具能夠有所幫助。另一個有效的辦法是適用Percona Server或MySQL5.6的快速預熱特性。
在配置連接池中的服務器時,要保證有足夠多未使用的容量,以備在撤下服務器做維護時適用,或者當服務求失效時可以派上用場。每臺服務器上都應該保留高于"足夠’的容量。
要確保配置的限制值足夠高,即使從池中撤出一些服務器也能夠工作。舉個例子,如果你發現每個MySQL服務器一般有100個連接,應該設置池中每個服務器的max_connections值為200.這樣就算一半的服務器失效,服務器池也能處理同樣數量的請求