1. 程式人生 > >MySQL架構設計談:從開發規範、選型、拆分到減壓(二)

MySQL架構設計談:從開發規範、選型、拆分到減壓(二)

2、運維規範

(1)SQL稽核

SQL評審這部分工作相信讓很多的DBA同學都叫苦不迭,人肉稽核不僅效率低下,容易出錯,對DBA的自身發展也非常不利,難道我們來上班就是為了稽核SQL的嗎?在經過了一段痛苦的人肉稽核之後,我們接入了去哪兒網開源的Inception,並根據自身的業務特點做了一些調整。當然現在開源的SQL評審軟體已經很多了,大家可以自由選擇,也可以自行開發。

在稽核與執行上線DDL語句的時候,要注意MySQL官方原生Online DDL和Percona公司的pt-osc之間的一些差異,例如pt-osc在執行時每次都要copy全表,相對來說比較慢,好處是不鎖表,並且有完善的條件檢測和延時負載策略控制。官方Online DDL雖然官方也一直在改進,但生產環境使用還不是很完美,尤其要注意執行過程中容易導致MDL鎖。官方Online DDL也有優於pt-osc的地方,比如增刪索引,重新命名列等,如下圖所示。

(2)許可權控制

Mysql從5.6開始,逐步完善了許可權系統,比如MySQL5.6可以安裝檢查密碼強度的外掛,5.7開始增加了密碼過期機制、賬戶鎖定等功能,對SSL這一塊也做了一些優化,8.0版本增加了角色的功能,許可權系統已經逐步在向Oracle資料庫靠攏了。在日常運維中,也可以使用pt-show-grants工具提高許可權審查的力度。應用程式賬號應只賦予SELECT、INSERT、UPDATE許可權,DELETE的邏輯改用UPDATE實現,並啟用sql_safe_updates選項。

另一個有效控制權限的方法就是SQL堡壘機,早期我們通過改造MyWebSQL實現,在Web版客戶端的基礎上加入了一些資源控制策略、審計、語法校驗等功能。後續又使用Python開發了功能更完備的SQL堡壘機,同時支援MySQL、Oracle、Greenplum等資料庫。

SQL堡壘機不僅可控制公司內部人員的資料庫許可權,追溯各類人員對資料庫的操作,也能避免大查詢或全表更新的情況發生,支援審計需求,整體運維質量提升了一個臺階。

(3)MySQL版本選擇MySQL社群版,使用者群體最大MySQL企業版,收費Percona Server版,新特性多,和MySQL社群版最接近MariaDB版,國內使用者暫時不多選擇優先順序:MySQL社群版> Percona Server > MariaDB > MySQL 企業版

對於版本選擇這件事,建議大家還是跟進官方社群版比較好,目前比較穩定的版本是MySQL5.6,推薦大家使用。有特殊需求的話再選擇MySQL5.7、PXC、TiDB、TokuDB等資料庫。二、MySQL高可用架構選型

MySQL高可用方面,目前業界主流依然是基於非同步複製的技術,例如Keepalived、MHA、ZooKeeper等,要求資料強一致的場景逐步開始使用分散式協議,這方面的典型代表有PXC、Group Replication、TiDB。下面我們就重點來說說keepalived、MHA和PXC這幾種大家用得比較多的架構。

1、keepalived高可用架構

業內使用非常普遍,它部署容易、方便維護,還節省伺服器資源。這種架構的一個好處就是在發生切換後,原Master只需重新拉起來即可恢復高可用,不需要過多幹預。擴充套件起來也方便,可以任意掛載只讀庫和災備庫。但它存在的問題也很明顯,比如Keepalived的檢測機制不完善、有腦裂隱患、資料一致性較弱等等。

還需要注意主從拓撲的設計。如下圖,只讀庫掛到哪個Master比較合適?顯然是M2,其它兩種拓撲在發生切換後都會影響到只讀庫的訪問。

2、MHA

MHA自誕生以來,就得到了業內的廣泛關注,並迅速流行開來。與keepalived相比,MHA最大的優點就是在發生故障切換之後,能自動補齊binlog,最大程度保證資料一致性。從伺服器能自動切換,無需人工干預,能非常好的工作在讀寫分離的環境下。基於Perl語言的指令碼也非常方便進行二次開發。MHA非常適合讀寫壓力比較大的應用。

但由於MHA在工作時需要配置SSH互信,因此選擇這種架構時內網安全一定要做到位。另外也可以搭配Binlog Server使用。

3、PXC

PXC全稱是Percona XtraDB Cluster,是Percona公司基於Galera協議開發的一個產品。PXC犧牲了CAP裡面的P(Partition Tolerance),保留了C(Consistency )和A(Availability )。這種結構非常適合電商、金融類業務,自PXC和Group Replication出現以後,MySQL徹底掃清了進入金融行業的障礙。

PXC的優勢:同步複製,解決了傳統架構複製延遲和腦裂的問題資料強一致多主複製,每個節點都可以讀寫資料並行複製,多個事務可以並行推送到其他節點高可用,單點故障不影響叢集可用性新節點自動部署與傳統MySQL幾乎完全相容

使用PXC要注意的問題:不要有大事務木桶效應,叢集效能取決於效能最差的那個節點併發效率有損失網路要求較高,建議萬兆網路多點併發寫時鎖衝突、死鎖問題多寫無法擴充套件,無法解決熱點更新問題

除此之外,還有一類採用DNS/ZooKeeper的高可用架構,這種架構通常都需要自行開發,無通用的方案,比較適合大規模叢集的高可用,這裡我們不過多贅述。

下面簡單回顧一下上述幾種高可用架構:雙Master架構:非常成熟,使用很普遍,要注意延遲和資料的一致性。PXC: 分散式協議,資料強一致性,併發效率略低,可用性好MHA:各項指標介於M-M和PXC之間,效能無損失,適合讀寫分離架構。

總而言之,沒有最完美的架構,只有最適合的架構。選擇適合自己業務的即可。三、MySQL sharding拆分

接下來是第三個議題,MySQL拆分原則和分庫分表設計。

首先先提一個問題,為什麼要拆,不拆不行嗎?按照我們的經驗來看,當資料和業務到了一定的規模,都不可避免的要面臨分庫分表的問題。這就好像汽車的發動機一樣,要達到更高的效能,4缸6缸明顯是不夠用的,V8、V12才是王道。

拆分能解決如下幾個問題:單庫併發較大單庫物理檔案太大單表過大,DDL無法接受防止出現效能瓶頸,提升效能防止出現抖動不穩定現象

確定要進行資料庫的拆分了,應該怎麼拆呢?

垂直拆分

優點:拆分簡單明瞭,拆分規則明確應用程式模組清晰,整合容易資料維護方便易行,容易定位

缺點:表關聯需要改到程式中完成事務處理變的複雜熱點表還有可能存在效能瓶頸過度拆分會造成管理複雜

水平拆分

優點:不會影響表關聯、事務操作超大規模的表和高負載的表可以打散應用程式端改動比較小拆分能提升效能,也比較易擴充套件

缺點:資料分散,影響聚集函式的使用切分規則複雜,維護難度增加後期遷移較複雜

要先分庫還是先分表?分庫的優點:實現簡單,庫與庫之間界限分明,便於維護,缺點是不利於頻繁跨庫操作,單表資料量大的問題解決不了。分表的優點:能解決分庫的不足點,但是缺點恰恰是分庫的優點,分表實現起來比較複雜,特別是分表規則的劃分,程式的編寫,以及後期的資料庫拆分移植維護。

一巴掌拍板直接選分庫或分表都是不可取的,主要是看需要達到什麼樣的擴充套件方式,才能決定先分庫還是先分表,根據具體的場景決定。分庫分表的最終目的還是為了擴充套件,而且要看拆分的規劃設計是針對哪一層。

上述問題都解決了,該考慮如何實現了,到底是在應用程式中實現,還是使用中介軟體?個人建議如果是小規模的拆分,直接在程式邏輯中實現即可,大規模的拆分再考慮使用各種中介軟體。

目前業內已經開源了很多的MySQL中介軟體產品,例如Atlas、DBProxy、MyCAT、OneProxy、DRDS、Vitess等等,每個中介軟體都有自己的特點,個別不太成熟的可能會存在一些Bug,選用之前要做好相關的調研與測試工作,上線使用一定要保證自己能hold住。如果要完全貼合自身業務,並且掌控得較好的還是要自行開發。

下面說說我們的拆分經驗。

首先我們先在壓力比較大的資料庫上做垂直拆分,剝離出活動、後臺統計等業務。這一步也是最容易實現的。

接下來,如果是訊息類的資料,就基於時間維度進行拆分,單表控制在5-10G,行數控制到500-1000w這個樣子。這個時候我們發現數據庫的效能是比較好的,而且比較好維護。如果是使用者類的資料,就按照Hash或Range進行拆分。這種情況下用這種方法拆分會拆的比較均勻一些。

併發仍然比較高怎麼辦?可以在時間維度拆分的基礎上再按Range或Hash進行拆分。

最後要注意的就是不要過度的拆分,會造成複雜度的上升。Schema設計合理的情況下,10億的資料量也能跑的好好的。個別不關鍵的應用,例如日誌、監控資料等,使用分割槽表、TokuDB也能抗。拆分對應用層總是有損的。

要做個“懶”DBA。

四、利用NoSQL為MySQL減壓

最後一個議題,我們聊一聊NoSQL。NoSQL現在遍地開花,應用也很廣泛了,業內用的比較多的主要集中在Redis、MongoDB、Cassandra等NoSQL資料庫上。今天我們主要來說說和MySQL關聯最為密切的Redis。

為什麼要使用Redis?資料儲存在記憶體中,訪問速度快能支援大批量操作及爆發性負載資料結構豐富,有效緩解MySQL壓力協議簡單,支援各種語言的API儲存大量資料無需擔心效能

Redis主要作用還是抗讀的壓力。讀操作先到Redis,Redis中取不到再從MySQL資料庫訪問,從MySQL讀取到資料後,還要回寫到Redis。

使用Redis要注意的幾點:

效能方面,由於Redis完全是基於記憶體的訪問,效能無需擔心。

在使用Redis時,要注意Cache 和Storage不要混合使用。不要依賴Redis的持久化,持久化這一塊Redis要努力的還很多。另外如果你把Redis拿來做Storage的話,一旦Redis的記憶體跑滿,那就慘了,所有的Redis連線都會卡著不響應。如果只是把Redis來做cache的話,那問題就不大。

還有諸如快取穿透、快取雪崩、熱點key重建時快取失效這些問題也是重點關注的物件。

如何利用Redis給MySQL加速:

1)利用K/V結構,快取結果,例如儲存使用者資訊、全域性排行、統計資訊等。

2)利用其豐富的資料結構為MySQL減壓,例如計數器、排序、Hash(把表對映到Redis中)、訊息佇列等。總結

系統架構設計是一個長期總結與進化的過程,講究均衡與取捨。在進行大規模MySQL架構設計的過程中,除了要汲取別人的經驗之外,還要關注各種架構背後的業務場景與架構思想,與自己的實際業務場景相結合,才能設計出一個好的系統架構來。