拆分的方法有多種,例如將原來主服務器上多個數據庫拆分到不同物理服務器的數據庫實例中。在一個MySQL數據庫中可能包含多個邏輯數據庫,在某個MySQL節點中存在多個邏輯數據庫,該節點不是一臺單一的MySQL數據庫服務器,而是MySQL數據庫集群,而且其中的所有數據庫中數據是一致的。
拆分的方法是將該節點中的不同數據庫拆分到不同的節點上。假設節點1中原本存在產品庫、銷售庫、倉儲庫,可以將其進行拆分,讓節點1中只包含產品庫,讓節點2只包含銷售庫,讓節點3只包含倉庫庫。這樣,就將原來節點1的寫壓力分擔到了三個節點上,大大減輕了MySQL節點一的負擔,提高了數據庫的運行效率。
這種拆分方式的特點是實現起來比較簡單,適用于不允許跨庫查詢的情況。只要對拆分后的數據庫重新配置連接,即可讓其正常運轉。其缺點是無法分擔針對單個數據庫的寫壓力。例如,銷售庫承擔了主要的寫壓力,別的數據庫讀寫的壓力很輕,那么這樣的拆分就意義不大。
為此,可以將原來數據庫中的表分離到不同節點中的不同數據庫中。在一個數據庫中會存在很多表,分別存儲不同類型的數據。例如對于節點1中的產品庫來說,可能包含衣服表、鞋帽表、食品表等,根據實際的分析,發現寫壓力主要集中在衣服表和食品表中,那么可以將這兩個表拆分到不同的數MySQL節點中。這樣,不同的節點只承受的只是原來數據庫中部分寫壓力。
我們還可以使用數據表的水平拆分加以應對。水平拆分即對數據庫進行分片處理,對一個數據庫中的相關表進行水平拆分,存放到不同實例的數據庫中。在大多數情況下,MySQL的分庫分表就是指的該種方式。
在實際的項目規劃中,如果沒有必要最好不要進行分片處理。當相關業務正常運行時,如果數據庫的并發操作沒有達到臨界值,就貿然對其進行分片,反倒變得難以維護,對運維產生不利影響。為了提高運維效能,應該首先考慮通過性能調優或者提高應用程序以及數據庫設計水平,來推遲分片操作。
例如,對于上述產品庫中的衣服表來說,當需要對其進行分片時,假設在節點1上只存在一個數據庫,其中只包含該數據表,經過分片處理后,會形成多個相同表結構的衣服表,這些表可能分布在不同的節點上。在對數據庫進行分片前,需要充分考慮到可能涉及到的問題。
如何選擇分區鍵決定了如何對數據庫進行分片,以及分片后如何查詢數據。分區鍵選擇的是否合適,直接決定了分區后數據庫的性能。在選擇分區鍵時,要盡可能的盡量避免發生跨分片查詢的情況。因為在這種情況下,應用程序必須對多個分片進行查詢后才可以合并查詢的結果信息,其效率甚至比分片前還要低。
例如,對于一個論壇來說,一個用戶可能在不同的板塊發布多篇帖子。如果以板塊的ID作為分區鍵,那么在查詢某個用戶時,就會跨所有的分區進行查詢,才能得到該用戶的所有帖子信息。如果以用戶的ID為分區鍵,可以保證同一個用戶的帖子全部在一個分片中,這樣查詢起來就更加快捷。
分區鍵的選擇要盡可能讓各個分片中的數據保持平均分布。之所以進行數據庫分片,是為了降低主數據庫的寫負載。如果分片后,大量的寫操作依然集中在某個分片中,就沒有必要進行分片。
對于一個在線訂單庫來說,如果以買家的ID為分區鍵,并且采用ID范圍來分片的話,就必須保證選擇的ID非常合理,大部分活躍的買家是否被分到了一個段中。如果分片后,所有的查詢都包含該分區鍵,使用哈希函數進行分區,無疑是最好的分區方式。
不管對于任何應用程序來說,往往只有少量的數據表需要進行分片處理,即只有少數的表才會被頻繁的寫入數據。
對于其他數據表來說,在分片后,可以在每個分片中存儲一份相同的數據。這就要求這些表數據量較小,不會被經常更新,而且這些表經常會被和分區表在一起進行關聯查詢,這樣在每一個分片中存儲一份冗余的數據表,可以提高查詢的效能。
當然,為了避免繁瑣的定期維護操作,可以將無需分片的數據表統一存儲在一個額外的節點中,讓整個MySQL集群不存在冗余問題。如果分片的表和這些表進行關聯查詢,就必須在應用程序中進行設置,對兩類數據表進行分別查詢并進行合并處理。因此,該方法的查詢效率較低。在節點上部署分片時,并不是在一個節點上只能部署一個分片,而是有很多種方式可以選擇。最簡單的方式是每個分片使用單一的數據庫,數據庫的名稱也保持一致。即每個數據庫的結構需要和原來單一實例上的數據庫結構相同。
也可以將多個分片表存儲在一個數據庫中,需要在對應的表名稱上加入分片號作為后綴,來進行明確的區分。
此外,還可以在每一個節點中部署多個數據庫,每個數據庫包含一個或者分片。之后按照上述方法對相關的數據庫和分片表進行區分。在一個節點中存儲多個數據庫實例的方法,也可以實現分片處理。
不管采用哪一種方法,相關的應用程序必須進行必要的調整,來匹配所采用的分片方式。如果在錯誤的分片中查詢數據,或者將數據寫入錯誤的分片,就會造成管理上的混亂。