MySQL主從複製(Master-Slave)與讀寫分離(MySQL-Proxy)實踐前端
Mysql做爲目前世界上使用最普遍的免費數據庫,相信全部從事系統運維的工程師都必定接觸過。但在實際的生產環境中,由單臺Mysql做爲獨立的數據庫是徹底不能知足實際需求的,不管是在安全性,高可用性以及高併發等各個方面。mysql
所以,通常來講都是經過 主從複製(Master-Slave)的方式來同步數據,再經過讀寫分離(MySQL-Proxy)來提高數據庫的併發負載能力 這樣的方案來進行部署與實施的。算法
以下圖所示:
sql
首先,咱們看一個圖:數據庫
影響MySQL-A數據庫的操做,在數據庫執行後,都會寫入本地的日誌系統A中。緩存
假設,實時的將變化了的日誌系統中的數據庫事件操做,在MYSQL-A的3306端口,經過網絡發給MYSQL-B。安全
MYSQL-B收到後,寫入本地日誌系統B,而後一條條的將數據庫事件在數據庫中完成。服務器
那麼,MYSQL-A的變化,MYSQL-B也會變化,這樣就是所謂的MYSQL的複製,即MYSQL replication。網絡
在上面的模型中,MYSQL-A就是主服務器,即master,MYSQL-B就是從服務器,即slave。架構
日誌系統A,其實它是MYSQL的日誌類型中的二進制日誌,也就是專門用來保存修改數據庫表的全部動做,即bin log。【注意MYSQL會在執行語句以後,釋放鎖以前,寫入二進制日誌,確保事務安全】
日誌系統B,並非二進制日誌,因爲它是從MYSQL-A的二進制日誌複製過來的,並非本身的數據庫變化產生的,有點接力的感受,稱爲中繼日誌,即relay log。
能夠發現,經過上面的機制,能夠保證MYSQL-A和MYSQL-B的數據庫數據一致,可是時間上確定有延遲,即MYSQL-B的數據是滯後的。
【即使不考慮什麼網絡的因素,MYSQL-A的數據庫操做是能夠併發的執行的,可是MYSQL-B只能從relay log中讀一條,執行下。所以MYSQL-A的寫操做很頻繁,MYSQL-B極可能跟不上。】
所謂的同步複製,意思是master的變化,必須等待slave-1,slave-2,...,slave-n完成後才能返回。
這樣,顯然不可取,也不是MYSQL複製的默認設置。好比,在WEB前端頁面上,用戶增長了條記錄,須要等待很長時間。
如同AJAX請求同樣。master只須要完成本身的數據庫操做便可。至於slaves是否收到二進制日誌,是否完成操做,不用關心。MYSQL的默認設置。
master只保證slaves中的一個操做成功,就返回,其餘slave無論。
這個功能,是由google爲MYSQL引入的。
問題1:master的寫操做,slaves被動的進行同樣的操做,保持數據一致性,那麼slave是否能夠主動的進行寫操做?
假設slave能夠主動的進行寫操做,slave又沒法通知master,這樣就致使了master和slave數據不一致了。所以slave不該該進行寫操做,至少是slave上涉及到複製的數據庫不能夠寫。實際上,這裏已經揭示了讀寫分離的概念。
問題2:主從複製中,能夠有N個slave,但是這些slave又不能進行寫操做,要他們幹嗎?能夠實現數據備份。
相似於高可用的功能,一旦master掛了,可讓slave頂上去,同時slave提高爲master。異地容災,好比master在北京,地震掛了,那麼在上海的slave還能夠繼續。主要用於實現scale out,分擔負載,能夠將讀的任務分散到slaves上。
【極可能的狀況是,一個系統的讀操做遠遠多於寫操做,所以寫操做發向master,讀操做發向slaves進行操做】
問題3:主從複製中有master,slave1,slave2,...等等這麼多MYSQL數據庫,那好比一個JAVA WEB應用到底應該鏈接哪一個數據庫?
當 然,咱們在應用程序中能夠這樣,insert/delete/update這些更新數據庫的操做,用connection(for master)進行操做,select用connection(for slaves)進行操做。那咱們的應用程序還要完成怎麼從slaves選擇一個來執行select,例如簡單的輪循算法。
這樣的話,至關於應用程序完成了SQL語句的路由,並且與MYSQL的主從複製架構很是關聯,一旦master掛了,某些slave掛了,那麼應用程序就要修改了。能不能讓應用程序與MYSQL的主從複製架構沒有什麼太多關係呢?能夠看下面的圖:
找一個組件,application program只須要與它打交道,用它來完成MYSQL的代理,實現SQL語句的路由。
mysql proxy並不負責,怎麼從衆多的slaves挑一個?能夠交給另外一個組件(好比haproxy)來完成。
這就是所謂的MYSQL READ WRITE SPLITE,MYSQL的讀寫分離。
問題4:若是mysql proxy , direct , master他們中的某些掛了怎麼辦?
總統通常都會弄個副總統,以防不測。一樣的,能夠給這些關鍵的節點來個備份。
問題5:當master的二進制日誌每產生一個事件,都須要發往slave,若是咱們有N個slave,那是發N次,仍是隻發一次?
若是隻發一次,發給了slave-1,那slave-2,slave-3,...它們怎麼辦?
顯 然,應該發N次。實際上,在MYSQL master內部,維護N個線程,每個線程負責將二進制日誌文件發往對應的slave。master既要負責寫操做,還的維護N個線程,負擔會很重。可 以這樣,slave-1是master的從,slave-1又是slave-2,slave-3,...的主,同時slave-1再也不負責select。 slave-1將master的複製線程的負擔,轉移到本身的身上。這就是所謂的多級複製的概念。
問題6:當一個select發往mysql proxy,可能此次由slave-2響應,下次由slave-3響應,這樣的話,就沒法利用查詢緩存了。
應該找一個共享式的緩存,好比memcache來解決。將slave-2,slave-3,...這些查詢的結果都緩存至mamcache中。
問題7:隨着應用的日益增加,讀操做不少,咱們能夠擴展slave,可是若是master知足不了寫操做了,怎麼辦呢?
scale on ?更好的服務器? 沒有最好的,只有更好的,太貴了。。。
scale out ? 主從複製架構已經知足不了。
能夠分庫【垂直拆分】,分表【水平拆分】。