MySQL架構方案

Scale Out:橫向擴展,增加處理節點提高整體處理能力
Scale Up:縱向擴展,通過提升單個節點的處理能力達到提升整體處理能力的目的

Replication
MySQL的replication是異步的,適用於對數據實時性要求不是特別關鍵的場景。slave端的IO線程負責從master讀取日誌,SQL線程專門負責在slave端應用從master讀過來的日誌(早期MySQL用一個線程實現,性能問題比較明顯)。使用replication必須啓用binary log,MySQL用binary log向slave分發更新

複製級別
1. Row Level:5.1.5開始支持。mater記錄每行數據的更改日誌,slave根據日誌逐行應用。優點:數據一致性更有保障。缺點:可能造成日誌文件比較大
2. Statement Level:master記錄每個執行的query語句以及一些上下文信息,slave節點根據這些信息重新在slave上執行。優點:binary log比較小。缺點:某些情況下數據一致性難以保障
3. Mixed Level:MySQL根據情況選擇哪種複製方式。5.1.8開始支持

常用架構
1. Master-Slaves:通常都採用這種方式
2. Dual Master(Master-Master):2個master節點互相同步更新。因爲MySQL的異步複製方式,爲了防止數據衝突造成的不一致性,一般僅將其中一臺用於寫操作,另一臺不用或僅用於讀操作。目的是其中一臺master停機維護或者故障中斷時可以使用另一臺master
3. 級聯複製(Master-Slaves-Slaves):在Master Slaves中,如果slaves過多replication將增加master的負載,這時可以讓master只向其中幾臺slave分發更新日誌,這幾臺slave作爲一級節點再向下級節點分發更新日誌

Cluster
主要通過NDB Cluster存儲引擎實現,是一個Share Nothing的架構,各個MySQL Server之間並不需要共享任何數據。可以實現冗餘(可靠性)以及負載均衡。剛開始MySQL需要所有數據和索引都能夠加載到內存中才能使用Cluster,對內存要求高,目前通過改進只要求索引能全部加載到內存

   
                  MySQL Clusrer架構示意圖,圖片來自MySQL官方文檔
1. SQL Nodes:負責存儲層之外的事情,例如連接管理、query處理和優化、cache管理等,即剝離了存儲層的MySQL服務器
2. Data Nodes:存儲層的NDB節點,即Cluster環境下的存儲引擎。每個cluster節點保存完整數據的一個分片,視節點數目和配置而定,一般data nodes被組織成爲一個個group,每個group存有一份完全相同的物理數據(冗餘)。NDB存儲引擎首先按照冗餘參數配置來使用存儲節點,然後根據節點數目對數據進行分段
3. Management Server:負責整個clsuter集羣中各個節點的管理工作,它保存了整個cluster環境的配置,啓動關閉各個節點,實現對各節點的常規維護、備份恢復等,它獲取各個節點的狀態和錯誤信息,並反映給整個集羣中所有節點

Cache
1. 應用層cache:最普通的cache方式,應用層自己管理cache,與數據庫無關
應用層cache的選擇方案很多
a). Memcached:分佈式的緩存,本身性能優秀,擴展性比較好;雖然比本地緩存方案慢,但具備共享緩存效果
b). Berkeley DB:與Memcached相比,BDB實現本地緩存;Memcached是內存式的緩存,而BDB使用磁盤,成本不一樣;Memcached僅支持hash索引,而BDB支持hash索引和B-Tree索引;MySQL數據庫方案下使用BDB,主要出於擴展性方面考慮,以及BDB的hash索引可以比MySQL更有效

2. MySQL-Memcached整合
:有2種方式
a). 直接用Memcached作爲MySQL的二級緩存。這可以增加MySQL的緩存容量,而Memcached對於應用端是不可見的。這種方案適用於一些特定場景,例如數據實在難以切分、很難對應用程序進行改造等
這種方案目前有Waffle Grid開源項目,僅支持InnoDB存儲引擎。其原理是當MySQL在Local Buffer Pool中找不到數據時則從磁盤讀取,而Waffle Grid在這裏加入一段處理,先嚐試從Memcached Server讀取,如果Memcached Server中不存在,才通過磁盤IO讀取,將讀取的數據會存入Memcached,並記錄在InnoDB Buffer Pool的LRU List中,如果數據變成dirty或者緩存管理將其清出時,InnoDB將對應的LRU List移入FLUSH List,此時Waffle Grid從Mamcached Server刪除數據。從上面可以看出,緩存機制仍然由MySQL管理,Memcached中存放的僅爲有效的(不是髒數據)、僅作爲緩存目的的數據,Memcached Server崩潰停機等不影響MySQL數據
架構示意圖(《MySQL性能調優與架構設計》):
   
Waffle Grid是否會因爲網絡訪問開銷導致查詢性能下降呢?可以參考Waffle Grid DBT2的測試結果,以及實際測試進行評估

b). 使用MySQL的UDF功能與Memcached進行整合。Memcached的數據由MySQL和應用端程序共同維護,應用端先從Memcached讀取數據,讀取不到時則從MySQL Server讀取,並把數據寫入Memcached中,而數據有更新、刪除導致Memcached數據失效時,MySQL負責將Memcached中相應數據清除
架構示意圖(《MySQL性能調優與架構設計》):
   
MySQL Memcached UDFs下載和使用參考Using the MySQL memcached UDFs

數據切分、Sharding
分爲垂直切分和水平切分,垂直切包括將一個表按不同字段切分成多個表、將不同表建在不同的MySQL Server中,水平切分指將同一個表的數據切分到多個表中存儲
1. 表結構設計垂直切分。常見的一些場景包括
a). 大字段的垂直切分。單獨將大字段建在另外的表中,提高基礎表的訪問性能,原則上在性能關鍵的應用中應當避免數據庫的大字段
b). 按照使用用途垂直切分。例如企業物料屬性,可以按照基本屬性、銷售屬性、採購屬性、生產製造屬性、財務會計屬性等用途垂直切分
c). 按照訪問頻率垂直切分。例如電子商務、Web 2.0系統中,如果用戶屬性設置非常多,可以將基本、使用頻繁的屬性和不常用的屬性垂直切分開

2. Sharding

Sharding指一種"shared nothing"形式的垂直切割,將切割後的部分部署在不同的服務器上。關於sharding和partition的區別可參考DBA Notes馮大輝的開源數據庫 Sharding 技術 (Share Nothing)
    
                             圖片來自DBA Notes: http://www.dbanotes.com
Sharding方案可以考慮:
a). Session-based sharding,只需在創建session時確定處理節點,隨後的請求都直接定向到該節點進行處理
b). Statement-based sharding,每個語句都需要確定處理節點
c). Transaction-based sharding,根據事務中第一條語句確定處理節點
Sharding潛在問題:
a). 被分割開的部分之間無法使用數據庫級別的join操作(cross-shard joins,可以考慮將一些公共的、全局的表部署到每一個節點上,使用replication機制分發)
b). 被分割開的部分之間事務處理複雜
c). 對自增長鍵的管理(主要出現在混合了水平切分的Sharding情況下)

3. 水平切分
示例:
a). 比如在線電子商務網站,訂單表數據量過大,按照年度、月度水平切分
b). Web 2.0網站註冊用戶、在線活躍用戶過多,按照用戶ID範圍等方式,將相關用戶以及該用戶緊密關聯的表做水平切分
c). 例如論壇的置頂帖子,因爲涉及到分頁問題,每頁都需要顯示置頂貼,這種情況可以把置頂貼水平切分開來,避免取置頂帖子時從所有帖子的表中讀取

難點之一,邏輯、關聯關係的複雜性阻礙水平切分。這樣的場景難在如何確定切分的範圍和策略,例如SAP這樣的大型ERP,模塊、表非常多,之間的邏輯複雜,SAP按每Client(公司、集團)將整個業務數據完全切分開,如果粒度需要再細化難度就非常大。方案一般有:a). 按主鍵切分;b). 維護一個主切割索引表,這種方案擴展性非常好,但是需要查找主索引表
第二點是如何使得水平切分具備擴展性。以Web 2.0網站爲例,如果按照會員ID範圍進行切分,假如現在決定水平切分爲5份,如果使用user_id % 5的值確定該用戶屬於哪個部分,這樣在將來隨着用戶量的增長,如果以後需要再切分成爲20份就會相當麻煩
水平切分和Sharding的混合模式,理論上可以實現線性伸縮,但受限於應用程序的狀況、設計以及切分、Sharding實現方案

切分和整合方案
主要2種實現思路:
1. 每個應用程序模塊配置管理自己需要的一個或多個數據源,直接訪問各個數據庫
2. 通過中間代理層統一管理所有的數據源,後端數據庫集羣架構對前端應用透明

使用MySQL Proxy
這是MySQL官方提供的,位於客戶端程序與MySQL Server之間,能夠監控、分析、轉換他們之間的通訊。常用的場景有負載均衡、故障恢復、查詢分析、查詢過濾和修改,以及基本的HA機制,目前在實現讀寫分離方面仍存在一些問題,架構示意圖(《MySQL性能調優與架構設計》):
   
MySQL Proxy提供一個基礎的框架,其他功能需要編寫LUA腳本實現(犧牲一定性能,帶來靈活性)
HSCALE是MySQL Proxy的一個LUA模塊,他透明的分析和重寫查詢,切分、分區邏輯從應用程序層轉移到代理層
HSCALE項目官方網站:http://www.hscale.org,作者博客網站:http://pero.blogs.aprilmayjune.org/

使用Amoeba
Amoeba是基於Java開發的分佈式數據庫數據源整合Proxy程序的開源框架,Amoeba 開發者博客項目主頁
主要解決以下問題:
a). 數據切分後複雜數據源整合
b). 提供數據切分規則並降低數據切分規則給數據庫帶來的影響
c). 降低數據庫與客戶端連接
d). 讀寫分離路由
Amoeba For MySQL是專門針對MySQL數據庫的方案,架構示意圖:
   
                圖片來自《MySQL性能調優與架構設計》
Amoeba For Aiadin是個更通用的方案,他前端接收MySQL協議的請求,後端可以使用MySQL、Oracle、PostGreSql等其他數據源,這些對應用程序是透明的。架構示意圖:
   
                圖片來自《MySQL性能調優與架構設計》

使用HiveDB
HiveDB也是基於Java的開源框架,有商業公司支持,目前僅支持水平切分,同時支持數據的冗餘及基本的HA機制。他使用Hibernate Shards實現數據水平切分,自行實現數據冗餘機制。HiveDB中通過用戶自定義的各種Partition keys將數據分散到多個MySQL Server,訪問時解析query請求,自動分析過濾條件,並行從多個MySQL Server讀取數據,合併結果集返回給客戶端應用程序。架構示意圖:
   
            圖片來自HiveDB官方網站: http://www.hivedb.org/
Hibernate Shards由Google貢獻,他使用標準的Hibernate編程模型,會用Hibernate就會用Hibernate Shards;可擴展的sharding策略;支持virtual shards,用於簡化resharding時的處理

Spock Proxy
由實際項目產生的一個開源項目(Spock是Rails的應用,Speck Proxy應當可用於Rails之外的,例如PHP或.NET),基於MySQL Proxy開發,是MySQL Proxy的一個分支,支持range-based horizontal paritioning,他對MySQL Proxy所做的改進包括:
a). 不使用LUA腳本,提升性能。例如將多個數據源返回的結果集合並期間還要與LUA腳本交互,這樣的性能開銷比較大
b). 客戶端登錄驗證。MySQL Proxy支持客戶端與各個服務器直接進行登錄驗證,Spock Proxy則將其統一管理,分離客戶端與服務器的連接
c). 動態連接池。受益於客戶端登錄認證機制的改善
d). 目前的MySQL Proxy無法做到讀寫分離,Spock Proxy實現了這一點,並且異步並行執行
架構示意圖:
   
             圖片來自Spock Proxy官方網站:http://spockproxy.sourceforge.net/

Pyshards
基於Python的Sharding方案,是一個個人研究開源項目,他的目標想實現自動re-balancing(re-sharding),比較有挑戰。目前僅支持MySQL。http://code.google.com/p/pyshards/

參考:《MySQL性能調優與架構設計》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章