1. 程式人生 > >java大併發之資料庫層面解決方案

java大併發之資料庫層面解決方案

    前言:當一個網站開始剛剛建立時,可能只是考慮一天只有幾十或者幾百個人訪問,資料庫可能就個db,所有表都放一起,一臺普通的伺服器可能就夠了,而且開發人員也非常高興,而且信心十足,因為所有的表都在一個庫中,這樣查詢語句就可以隨便關聯了,多美的一件事情。但是隨著訪問壓力的增加,讀寫操作不斷增加,資料庫的壓力絕對越來越大,可能接近極限,這時可能人們想到增加從伺服器,做什麼叢集之類的,可是問題又來了,資料量也快速增長。這時可以考慮對資料庫讀寫操作進行分離,按照業務把不同的資料放到不同的庫中。其實在一個大型而且臃腫的資料庫中表和表之間的資料很多是沒有關係的,或者更加不需要(join)操作,理論上就應該把他們分別放到不同的伺服器。例如使用者的收藏夾的資料和部落格的資料庫就可以放到兩個獨立的伺服器。這個就叫垂直劃分。把一個表的資料按規律分到不同的資料庫,兩個資料庫表結構一樣,就叫資料庫的水平拆分。

  1. 資料庫垂直劃分(資料庫表無關聯)

按照功能劃分,把資料分別放到不同的資料庫和伺服器上,即為資料庫的垂直劃分。垂直拆分取決於當前模組要拆分的表是否有關聯。比如工資模組和員工工資檔案模組是沒有關聯的,該兩個模組對應的表獨立,就可以拆分。

http://dl.iteye.com/upload/attachment/224720/afae64b0-b31c-398c-8688-e4c685116d54.png

  1. 資料庫水平劃分

資料庫水平拆分是將一個表的資料換分到不同資料庫,兩個資料庫表結構一樣。

對於表的拆分是要根據一樣的規則,例如根據id拆分,然後根據一定的規則先獲知要操作的資料在哪個資料庫。一剛才的部落格為例,可以根據使用者id的奇偶數來確定資料的劃分,把奇數劃到A資料庫,偶數劃到B資料庫,所以通過userId%2就可以判斷該資料在哪個資料庫了;或者將前5千萬條資料放到A資料庫,後面的資料放到B資料庫,再者還可以根據Hash演算法來處理。

http://dl.iteye.com/upload/attachment/224943/fa8080ad-d0ed-3784-b95d-85f9969a7225.png

3.資料庫讀寫分離

資料庫讀寫分離,基本的原理是讓資料庫處理事務性增、改、刪操作(INSERT、UPDATE、DELETE),而從資料庫處理SELECT查詢操作。資料庫複製被用來把事務性操作導致的變更同步到叢集中的從資料庫。

 

資料庫分庫、分表、讀寫分離的原因:

 單表的資料量限制,當單表資料量到一定條數之後資料庫效能會顯著下降。資料多了之後,對資料庫的讀、寫就會很多。分庫減少單臺數據庫的壓力。接觸過幾個分庫分表的系統,都是通過主鍵進行雜湊分庫分表的。這類資料比較特殊,主鍵就是唯一的獲取該條資訊的主要途徑。比如:京東的訂單、財付通的交易記錄等。。。該類資料的用法,就是通過訂單號、交易號來查詢該筆訂單、交易。

還有一類資料,比如使用者資訊,每個使用者都有系統內部的一個userid,與userid對應的還有使用者看到的登入名。那麼如果分庫分表的時候單純通過userid進行雜湊分庫,那麼根據登入名來獲取使用者的資訊,就無法知道該使用者處於哪個資料庫中。

或許有朋友會說,我們可以維護一個email—-userid的對映關係,根據email先查詢到userid,在根據userid的分庫分表規則到對應庫的對應表來獲取使用者的記錄資訊。這麼做是可以的,但是這個對映關係的條數本身也是個瓶頸,原則上是沒有減少單表內資料的條數,算是一個單點。並且要維護這個對映關係和使用者資訊的一致性(修改登入名、多登入名等其他特殊需求),最大一個原因,其實使用者資訊是一個讀大於寫的庫,web2.0都是以使用者為中心,所有資訊都和使用者資訊相關聯,所以對使用者資訊拆分還是有一定侷限性的。對於這類讀大於寫並且資料量增加不是很明顯的資料庫,推薦採用讀寫分離+快取的模式,試想一下一個使用者註冊、修改使用者資訊、記錄使用者登入時間、記錄使用者登入IP、修改登入密碼,這些是寫操作。但是以上這些操作次數都是很小的,所以整個資料庫的寫壓力是很小的。唯一一個比較大的就是記錄使用者登入時間、記錄使用者登入IP這類資訊,只要把這些經常變動的資訊排除在外,那麼寫操作可以忽略不計。所以讀寫分離首要解決的就是經常變化的資料的拆分,比如:使用者登入時間、記錄使用者登入IP。這類資訊可以單獨獨立出來,記錄在持久化類的快取中(可靠性要求並不高,登陸時間、IP丟了就丟了,下次來了就又來了)

Oracle為例,主庫負責寫資料、讀資料。讀庫僅負責讀資料每次有寫庫操作,同步更新cache,每次讀取先讀cache(快取伺服器叢集是為了減輕資料庫負擔)在讀DB寫庫就一個,讀庫可以有多個,採用dataguard來負責主庫和多個讀庫的資料同步。

http://my.csdn.net/uploads/201205/29/1338293588_6347.jpg

利用資料庫同步軟體完成主從資料庫的同步。例如:dataguard;