記得在上一篇文章「Java集羣--大型網站是怎樣解決多用戶高併發訪問的」的結尾處本人闡述了數據庫的高可用的一種方案----實現主從部署,那麼今天,就讓我聊聊本人關於數據庫的一些所思所想吧!html
下面是本人對數據庫的高可用性的一些見解:mysql
提出緣由:當網站或運用爲用戶提供服務時,防止單點故障問題,而且經過必定的分發策略來提高數據庫的安全性和可用性。sql
問題注重點:架構的可拓展性,而經常使用的拓展手段有兩種,分別是Scale-up和Scale-out。那麼何爲Scale-up和Scale-out呢?Scale-up即縱向拓展,經過替換爲更好的機器和資源來實現伸縮,提高服務能力;Scale-out即橫向拓展,經過加節點(機器)來實現伸縮,提高服務能力。然而對於互聯網的高併發運用來講,無疑Scale-out纔是出路,它的理想狀態是一個服務,當面臨更高的併發的時候,可以經過簡單增長機器來提高服務支撐的併發度,且增長機器過程當中對線上服務無影響。數據庫
對於大部分的小型運用,咱們常常會把全部的數據存放在一個服務器上的一個數據庫上,以此來知足小型數據的讀取和寫入功能(架構圖以下)。安全
對於這種架構,它的瓶頸是:服務器
1.讀寫都在同一個數據庫實體上,使得數據庫的讀寫壓力增大,響應用戶的時間就會相應的加長架構
2.並且隨着數據量的增大,大到數據庫的實體的容量已經放不下,那麼這種架構拓展起來就很是麻煩了。看到這裏千萬別說「直接再加一臺服務器不就好了嗎?」併發
3.全部的數據都放在同一個服務器上,若是這臺服務器掛掉了,這個系統也癱瘓了,更坑的是,若是這臺服務器已經被破壞的體無完膚了(多是地震),那麼以前的數據也就沒法再次獲取了,即系統的容災性差。(PS:也許你很期盼某個網站出現這種狀況,這樣女友的帳單就不用付了。。。別想太多,通常比較大型的網站,都會把數據備份到不一樣的服務器的數據庫上,並且相鄰兩臺服務器不止相隔甚遠,連在同一個經度和緯度都是儘可能避諱的)負載均衡
經過上面的分析可知,在單庫中,運用的系統性能是比較低的,並且容災性差,因此做爲一名比較負責任的代碼寫手,怎麼可以忍受這種響應速度慢且又不可靠的架構出如今本身的項目中呢?看到這裏,也許你會想到把咱們的數據放到多臺的服務器上的數據庫中,這樣容災性就好不少了,並且若是在數據庫的前面再加上一個代理,實現數據庫操做語句的分發策略,這樣子每臺服務器的數據庫的操做的壓力也就減小了,也就是程序響應用戶的速度也相應加快了,恩恩,你的想法已經能解決上面的單機版的有些問題了,但你可知道你的這種架構有個很好聽的名字嗎?不繞彎子了,它就是負載均衡技術(這裏就以數據庫按垂直切分來討論討論這套架構吧!PS:另一種數據庫切分方案是水平切分)高併發
如何經過負載均衡技術來實現數據庫的集羣呢?先上整體架構圖(這裏的數據庫暫時以mysql爲例)
實現原理:首先要有一個能夠控制鏈接數據庫的控制端(好比這裏的mycat,mycat的前生是阿里巴巴的cobar,因此感受不會太差),在這裏,它截斷了數據庫與程序的直接鏈接,由全部的程序來訪問這個中間層,而後再由中間層來訪問數據庫。這樣咱們就能夠根據數據庫的當前負載採起有效的均衡策略,來調整每次鏈接到哪一個數據庫。
若是採用mycat來做爲mysql集羣的代理,咱們能夠比較容易的實現上圖的整體架構,在正常的狀況下,只有一臺「寫」節點(上圖的Master1)負責數據庫的全部寫操做,其餘的從(上圖的slave1~5和Master2)或主從數據庫來充當「讀」的角色,一旦Master1掛掉以後,mycat會把它切換到Master2,且把Master1下的全部從節點(slave1~3)也同時從「讀」節點剔除掉(PS:想一想這樣有什麼好處),這樣負責「讀」的就有Slave四、5,一旦Master1心跳恢復,他就變成了「寫」節點Master2的主從節點了。
固然,mycat是沒有幫咱們實現數據庫之間數據的同步的問題的,但咱們可使用mysql自帶的Master-Slave Replication方式來實現每一個數據庫的同步,但又很不幸,這種方式並不能徹底的保證服務器上的數據都是實時同步的,若是你的程序沒有作一些特殊的處理,那麼這種方式只能說是「保證數據最終結果的一致性」。
其實,針對mysql來講,這種架構其實還有一項很是重要的優化措施,不知讀者有沒有發現,咱們在上面的第二個架構中使用了數據庫的讀寫分離,咱們都知道,mysql的數據庫引擎主要是有兩大類(Innodb和MyIsam),其中,咱們知道MyIsam在查詢時的性能會比較高,因此,在本次架構中,咱們會把「寫」節點的數據庫引擎改成Innodb,而把「讀」節點改成MyIsam引擎。
一家之言,歡迎各位前輩的拍磚。
最近在看「深刻理解Java虛擬機」一書,因此後續會寫一篇文章來簡潔介紹關於Java GC的祕密。