1. 概述
創(chuàng)新互聯-專業(yè)網站定制、快速模板網站建設、高性價比麥蓋提網站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式麥蓋提網站制作公司更省心,省錢,快速模板網站建設找我們,業(yè)務覆蓋麥蓋提地區(qū)。費用合理售后完善,十余年實體公司更值得信賴。
我們在考慮MySQL數據庫的高可用的架構時,主要要考慮如下幾方面:
關于對高可用的分級在這里我們不做詳細的討論,這里只討論常用高可用方案的優(yōu)缺點以及高可用方案的選型。
2. 高可用方案
2.1. 主從或主主半同步復制
使用雙節(jié)點數據庫,搭建單向或者雙向的半同步復制。在5.7以后的版本中,由于lossless replication、logical多線程復制等一些列新特性的引入,使得MySQL原生半同步復制更加可靠。
常見架構如下:
通常會和proxy、keepalived等第三方軟件同時使用,即可以用來監(jiān)控數據庫的 健康 ,又可以執(zhí)行一系列管理命令。如果主庫發(fā)生故障,切換到備庫后仍然可以繼續(xù)使用數據庫。
優(yōu)點:
缺點:
2.2. 半同步復制優(yōu)化
半同步復制機制是可靠的。如果半同步復制一直是生效的,那么便可以認為數據是一致的。但是由于網絡波動等一些客觀原因,導致半同步復制發(fā)生超時而切換為異步復制,那么這時便不能保證數據的一致性。所以盡可能的保證半同步復制,便可提高數據的一致性。
該方案同樣使用雙節(jié)點架構,但是在原有半同復制的基礎上做了功能上的優(yōu)化,使半同步復制的機制變得更加可靠。
可參考的優(yōu)化方案如下:
半同步復制由于發(fā)生超時后,復制斷開,當再次建立起復制時,同時建立兩條通道,其中一條半同步復制通道從當前位置開始復制,保證從機知道當前主機執(zhí)行的進度。另外一條異步復制通道開始追補從機落后的數據。當異步復制通道追趕到半同步復制的起始位置時,恢復半同步復制。
搭建兩條半同步復制通道,其中連接文件服務器的半同步通道正常情況下不啟用,當主從的半同步復制發(fā)生網絡問題退化后,啟動與文件服務器的半同步復制通道。當主從半同步復制恢復后,關閉與文件服務器的半同步復制通道。
優(yōu)點:
缺點:
2.3. 高可用架構優(yōu)化
將雙節(jié)點數據庫擴展到多節(jié)點數據庫,或者多節(jié)點數據庫集群??梢愿鶕约旱男枰x擇一主兩從、一主多從或者多主多從的集群。
由于半同步復制,存在接收到一個從機的成功應答即認為半同步復制成功的特性,所以多從半同步復制的可靠性要優(yōu)于單從半同步復制的可靠性。并且多節(jié)點同時宕機的幾率也要小于單節(jié)點宕機的幾率,所以多節(jié)點架構在一定程度上可以認為高可用性是好于雙節(jié)點架構。
但是由于數據庫數量較多,所以需要數據庫管理軟件來保證數據庫的可維護性??梢赃x擇MMM、MHA或者各個版本的proxy等等。常見方案如下:
MHA Manager會定時探測集群中的master節(jié)點,當master出現故障時,它可以自動將最新數據的slave提升為新的master,然后將所有其他的slave重新指向新的master,整個故障轉移過程對應用程序完全透明。
MHA Node運行在每臺MySQL服務器上,主要作用是切換時處理二進制日志,確保切換盡量少丟數據。
MHA也可以擴展到如下的多節(jié)點集群:
優(yōu)點:
缺點:
Zookeeper使用分布式算法保證集群數據的一致性,使用zookeeper可以有效的保證proxy的高可用性,可以較好的避免網絡分區(qū)現象的產生。
優(yōu)點:
缺點:
2.4. 共享存儲
共享存儲實現了數據庫服務器和存儲設備的解耦,不同數據庫之間的數據同步不再依賴于MySQL的原生復制功能,而是通過磁盤數據同步的手段,來保證數據的一致性。
SAN的概念是允許存儲設備和處理器(服務器)之間建立直接的高速網絡(與LAN相比)連接,通過這種連接實現數據的集中式存儲。常用架構如下:
使用共享存儲時,MySQL服務器能夠正常掛載文件系統并操作,如果主庫發(fā)生宕機,備庫可以掛載相同的文件系統,保證主庫和備庫使用相同的數據。
優(yōu)點:
缺點:
DRBD是一種基于軟件、基于網絡的塊復制存儲解決方案,主要用于對服務器之間的磁盤、分區(qū)、邏輯卷等進行數據鏡像,當用戶將數據寫入本地磁盤時,還會將數據發(fā)送到網絡中另一臺主機的磁盤上,這樣的本地主機(主節(jié)點)與遠程主機(備節(jié)點)的數據就可以保證實時同步。常用架構如下:
當本地主機出現問題,遠程主機上還保留著一份相同的數據,可以繼續(xù)使用,保證了數據的安全。
DRBD是linux內核模塊實現的快級別的同步復制技術,可以與SAN達到相同的共享存儲效果。
優(yōu)點:
缺點:
2.5. 分布式協議
分布式協議可以很好解決數據一致性問題。比較常見的方案如下:
MySQL cluster是官方集群的部署方案,通過使用NDB存儲引擎實時備份冗余數據,實現數據庫的高可用性和數據一致性。
優(yōu)點:
缺點:
基于Galera的MySQL高可用集群, 是多主數據同步的MySQL集群解決方案,使用簡單,沒有單點故障,可用性高。常見架構如下:
優(yōu)點:
缺點:
Paxos 算法解決的問題是一個分布式系統如何就某個值(決議)達成一致。這個算法被認為是同類算法中最有效的。Paxos與MySQL相結合可以實現在分布式的MySQL數據的強一致性。常見架構如下:
優(yōu)點:
缺點:
3. 總結
隨著人們對數據一致性的要求不斷的提高,越來越多的方法被嘗試用來解決分布式數據一致性的問題,如MySQL自身的優(yōu)化、MySQL集群架構的優(yōu)化、Paxos、Raft、2PC算法的引入等等。
而使用分布式算法用來解決MySQL數據庫數據一致性的問題的方法,也越來越被人們所接受,一系列成熟的產品如PhxSQL、MariaDB Galera Cluster、Percona XtraDB Cluster等越來越多的被大規(guī)模使用。
隨著官方MySQL Group Replication的GA,使用分布式協議來解決數據一致性問題已經成為了主流的方向。期望越來越多優(yōu)秀的解決方案被提出,MySQL高可用問題可以被更好的解決。
分布式解決方案 tidb
多主 多備 master lvs做vip 讀寫分離中間件
一個事務要更新一行,如果剛好有另外一個事務擁有這一行的行鎖,會被鎖住,進入等待狀態(tài)。既然進入了等待狀態(tài),那么等到這個事務自己獲取到行鎖要更新數據的時候,它讀到的值又是什么呢?
可重復讀隔離級別下,事務在啟動的時候就“拍了個整個庫的快照”。如果一個庫有100G,那么我啟動一個事務,MySQL就要拷?100G的數據出來,這個過程得多慢啊。但是平時事務執(zhí)行起來卻是非??斓摹2皇侨靠截惓鰜砟鞘窃趺磳崿F的呢?
InnoDB里面每個事務有一個唯一的事務ID,叫作transaction id。它是在事務開始的時候向InnoDB的事務系統申請的,是按申請順序嚴格遞增的。
而每行數據也都是有多個版本的。每次事務更新數據的時候,都會生成一個新的數據版本,并且把transaction id賦值給這個數 據版本的事務ID,記為row trx_id。同時,舊的數據版本要保留,并且在新的數據版本中,能夠有信息可以直接拿到它。
數據表中的一行記錄,其實可能有多個版本(row),每個版本有自己的row trx_id。
圖中虛線框里是同一行數據的4個版本,當前最新版本是V4,k的值是22,它是被transaction id 為25的事務更新的,因此它的row trx_id也是25。語句更新會生成undo log(回滾日志),圖中的三個虛線箭頭,就是undo log。
按照可重復讀的定義,一個事務啟動的時候,能夠看到所有已經提交的事務結果。但是之后,這個事務執(zhí)行期間,其他事務的更新對它不可?。
一個事務只需要在啟動的時候聲明說,“以我啟動的時刻為準,如果一個數據版本是在我啟動之前生成的,就認;如果是我啟動以后才生成的,我就不認,我必須要找到它的上一個版本”。
如果“上一個版本”也不可?,那就得繼續(xù)往前找。如果是這個事務自己更新的數據,它自己還是要認的。
在實現上, InnoDB為每個事務構造了一個數組,用來保存這個事務啟動瞬間,當前正在“活躍”的所有事務ID?!盎钴S”指的就 是,啟動了但還沒提交。數組里面事務ID的最小值記為低水位,當前系統里面已經創(chuàng)建過的事務ID的最大值加1記為高水位。 這個視圖數組和高水位,就組成了當前事務的一致性視圖(read-view)。而數據版本的可?性規(guī)則,就是基于數據的row trx_id和這個一致性視圖的對比結果得到的。
InnoDB利用了“所有數據都有多個版本”的這個特性,實現了“秒級創(chuàng)建快照”的能力。
回到我們最開始的表格,看看最后執(zhí)行的結果是多少。做如下假設:
事務A的視圖數組就是[99,100], 事務B的視圖數組是[99,100,101], 事務C的視圖數組是[99,100,101,102]。為了簡化分析,我先把其他干擾語句去掉,只畫出跟事務A查詢邏輯有關的操作:
第一個有效更新是事務C,把數據從(1,1)改成了(1,2)。這時候,這個數據的最新版本的row trx_id是102,而90這個版本已經成為了歷史版本。 第二個有效更新是事務B,把數據從(1,2)改成了(1,3)。這時候,這個數據的最新版本(即row trx_id)是101,而102又成為了歷史版本。
事務B的update語句,如果按照一致性讀,好像結果不對哦?
事務B的視圖數組是先生成的,之后事務C才提交,不是應該看不?(1,2)嗎,怎么能算出(1,3)來?
事務B在更新之前查詢一次數據,這個查詢返回的k的值確實是1。 但是,當它要去更新數據的時候,就不能再在歷史版本上更新了,否則事務C的更新就丟失了。因此,事務B此時的set k=k+1是在(1,2)的基礎上進行的操作。 所以,這里就用到了這樣一條規(guī)則:更新數據都是先讀后寫的,而這個讀,只能讀當前的值,稱為 “當前讀” ( current read )。
在更新的時候,當前讀拿到的數據是(1,2),更新后生成了新版本的數據(1,3),這個新版本的row trx_id是101。
所以,在執(zhí)行事務B查詢語句的時候,一看自己的版本號是101,最新數據的版本號也是101,是自己的更新,可以直接使用, 所以查詢得到的k的值是3。
select語句如果加鎖,也是當前讀。
如果把事務A的查詢語句select * from t where id=1修改一下,加上lock in share mode 或 for update,也都可以讀到版本號是101的數據,返回的k的值是3。下面這兩個select語句,就是分別加了讀鎖(S鎖,共享鎖)和寫鎖(X鎖,排他鎖)。
事務C’的不同是,更新后并沒有?上提交,在它提交前,事務B的更新語句先發(fā)起了。前面說過了,雖然事務C’還沒提交,但是(1,2)這個版本也已經生成了,并且是當前的最新版本。那么,事務B的更新語句會怎么處理呢?
兩階段鎖協議,事務C’沒提交,也就是說(1,2)這個版本上的寫鎖還沒釋放。 而事務B是當前讀,必須要讀最新版本,而且必須加鎖,因此就被鎖住了,必須等到事務C’釋放這個鎖,才能繼續(xù)它的當前讀。
回到最初的問題,事務的可重復讀的能力是怎么實現的?
索引的創(chuàng)建很簡單,可以網上查下相關信息,在這里只是說下索引需要注意的地方,索引分為很多不同的類型,一般咱們說的是B_Tree索引,這里就只說B_Tree,如果是哈希索引,可以網上找相關資料。
.B_Tree適用于:
1.全值匹配
全值匹配是指和索引中的所有列進行匹配。
2.匹配最左前綴
匹配左左前綴即只使用索引的第一列
3.匹配列前綴
匹配某一列開頭部分(指的第一列)。
4.匹配范圍值
5.精確匹配某一列并范圍匹配另一列
6.只訪問索引的查詢
只需訪問索引,無需訪問數據行。
.B_Tree限制
1.如果不是按照索引的最左列開始查找,則無法使用索引。
2.不能跳過索引中的列。
3.如果查詢中有某個列的范圍查詢,則其右邊左右列無法使用索引優(yōu)化查找。
索引是滿足某種特定查找算法的數據結構,而這些數據結構會以某種方式指向數據,從而實現高效查找數據。
具體來說 MySQL 中的索引,不同的數據引擎實現有所不同,但目前主流的數據庫引擎的索引都是 B+ 樹實現的,B+ 樹的搜索效率,可以到達二分法的性能,找到數據區(qū)域之后就找到了完整的數據結構了,所有索引的性能也是更好的。