天天看點

資料庫讀寫分離與垂直分庫水準分表

讀寫分離

随着一個網站的業務不斷擴充,資料不斷增加,資料庫的壓力也會越來越大,對資料庫或者SQL的基本優化可能達不到最終的效果,我們可以采用讀寫分離的政策來改變現狀。讀寫分離現在被大量應用于很多大型網站,這個技術也不足為奇了。

讀寫分離簡單的說是把對資料庫讀和寫的操作分開對應不同的資料庫伺服器,這樣能有效地減輕資料庫壓力,也能減輕io壓力。主資料庫提供寫操作,從資料庫提供讀操作,其實在很多系統中,主要是讀的操作。當主資料庫進行寫操作時,資料要同步到從的資料庫,這樣才能有效保證資料庫完整性。

mysql隻要是通過二進制日志來複制資料。複制的方式有兩種

1.基于語句的複制:資料庫會記錄導緻改變的查詢,并将這些sql在從庫上重新執行一遍。它的優點是簡單,易實作,并且二進制日志檔案比較緊湊,因為幾十MB的資料的語句可能隻有幾十位元組而已。并且靈活性高,列的順序,不一緻但相容的資料類型,都可以執行,當需要修改schema的時候,可以在備庫上改完提升為主庫,減少當機時間。缺點就是某些資料不能準确的複制,比如帶時間戳的,或者含有某些特定函數值的。并且語句的執行必須是串行的,是以會消耗不少的鎖資源。

2.基于行的複制:這種方式就是把實際的資料記錄到二進制日志裡,因為是把資料直接複制,是以不必擔心資料正确性的問題。并且在某些情況下性能比基于語句的更快,比如group by之後插入,當組合比較少的時候,隻需要插入少量資料,而基于語句的則必須掃描全表。但像如果改動以where為條件,且範圍較大的時候,基于行的表現就不如語句了。但是基于行的複制不需要串行執行,也不需要建立查詢,cpu占用少

mysql從5.1開始支援動态的複制算法,預設基于語句,當基于語句無法複制正确的結果時,再基于行複制。通過日志在從資料庫重複主資料庫的操作達到複制資料目的。這個複制比較好的就是通過異步方法,把資料同步到從資料庫。

基于主從複制的可分為以下三步:

第一步是主庫記錄二進制日志,并且是在每次準備送出事務之前寫入的日志,日記記錄完畢才會送出事務。

第二步備庫會啟動一個工作線程不斷的把主庫的二進制日志拷貝到自己的中繼日志中,如果追上了主庫的最新日志,則睡眠,知道被主庫發送信号量将其喚醒。

第三步備庫的sql線程讀取中繼日志并在備庫上執行更新操作。

讀寫分離就是在主從複制的基礎上,将讀請求交由slave伺服器處理,寫請求交給master伺服器處理

貼一篇關于讀寫分離主從複制比較好的一篇部落格:

http://zhangfengzhe.blog.51cto.com/8855103/1563032

垂直分庫、水準分表

垂直劃分

按照功能劃分,把資料分别放到不同的資料庫和伺服器。

當一個網站開始剛剛建立時,可能隻是考慮一天隻有幾十或者幾百個人通路,資料庫可能就個db,所有表都放一起,一台普通的伺服器可能就夠了,而且開發人員也非常高興,而且信心十足,因為所有的表都在一個庫中,這樣查詢語句就可以随便關聯了,多美的一件事情。但是随着通路壓力的增加,讀寫操作不斷增加,資料庫的壓力絕對越來越大,可能接近極限,這時可能人們想到增加從伺服器,做什麼叢集之類的,可是問題又來了,資料量也快速增長。

這時可以考慮對讀寫操作進行分離,按照業務把不同的資料放到不同的庫中。其實在一個大型而且臃腫的資料庫中表和表之間的資料很多是沒有關系的,或者更加不需要(join)操作,理論上就應該把他們分别放到不同的伺服器。例如使用者的收藏夾的資料和部落格的資料庫就可以放到兩個獨立的伺服器。這個就叫垂直劃分(其實叫什麼不重要)。

資料庫讀寫分離與垂直分庫水準分表

當部落格或者收藏夾的資料不斷增加後,應該怎麼辦,這樣就引出了另外一個做法,叫水準劃分。

水準劃分

則把一個表的資料劃分到不同的資料庫,兩個資料庫的表結構一樣。怎麼劃分,應該根據一定的規則,可以根據資料的産生者來做引導,上面的資料是由人産生的,可以根據人的id來劃分資料庫。然後再根據一定的規則,先獲知資料在哪個資料庫。

其實很多大型網站都經曆了資料庫垂直劃分和水準的劃分的階段。其實這個可以根據經驗來确定,不一定由某些硬性的規則。

以剛才的部落格為例,資料可以根據userid的奇偶來确定資料的劃分。把id為基數的放到A庫,為偶數的放B庫。

資料庫讀寫分離與垂直分庫水準分表

這樣通過userId就可以知道使用者的部落格的資料在哪個資料庫。其實可以根據userId%10來處理。還可以根據著名的HASH算法來處理。