第4章 資料訪問層
阿新 • • 發佈:2019-02-07
上一章的服務框架可以讓應用從集中式走向分散式,解決了當網站功能越來越豐富、單個應用越來越龐大的問題,使系統走向服務化的架構。隨著資料量和訪問量的上升,應用訪問資料庫也會出現瓶頸,這時資料訪問層出場!
4.1 資料庫從單機到分散式的挑戰
4.1.1 單機資料庫
當網站比較小,資料庫的數量和訪問量都比較小時,只有一個數據庫,所有的table 都在這個資料庫中;這個資料庫服務可能是單獨一臺伺服器,也可能跟應用或者其他服務共用一臺伺服器;然後應用用資料訪問層(JDBC/ODBC)來統一訪問資料庫;這個資料訪問層可以提供給開發一套API,讓開發更方便的訪問資料庫。
APP ------> JDBC ---> DB
4.1.2 資料庫垂直、水平拆分的困難
當網頁訪問量足夠大時,除了簡單的加機器來提高訪問的效率外,還有其他的幾種思路可以緩解DB的壓力:
- 應用的優化:可以通過業務的優化和訪問db的優化來減少DB的訪問、或者錯開高峰的訪問
- 引入快取:可以引入快取、搜尋引擎之類的來緩解DB的壓力
- 對資料庫進行分庫、分表;把DB 升級到分散式資料庫
- 打破原來的ACID 原則:比如之前單機的事務,DBMS 可以自帶ACID 原則,但是分散式的DB 需要應用自己來保證事務的一致性或者引入分散式的事務
- join 工作:因為多張table 可能不在同一個資料庫裡面,這時就不能簡單使用DBMS的join工作,需要應用從不同的DB 不同的table 裡面取出資料,然後自己程式碼中進行join
- 分表的動作:唯一的id編號的key 就會遇到問題,這些問題都需要在分散式DB 中進行解決
- 觸發器、儲存過程:從單機DB 遷移到分散式DB 後這些有可能都會失效,都需要重新修改後才可以使用
4.2 資料庫從單機變為多機(分散式)如何處理
4.2.1 分散式事務
事務的支援對應用來說是非常重要的特性,對單臺DB的DBMS 支援是非常到位的,但是在分散式的DB中事務的特性就需要應用自己來解決;下面看下怎麼解決的:- 分散式事務(DTP):
- 分散式事務的解決方案
4.2.2 多機的sqeuence 的處理
當水平分表時,單機中的sequence和自增的id做法就需要改變,在單機的DBMS中提供了一個機制來實現自增、不重複的id來完成編號;但在分散式資料庫中就變的困難,這個問題主要解決的思路分為2個問題:一個是唯一性、一個是連續性; 如果2個問題單獨考慮會非常簡單:唯一性可以用ip、mac地址、時間等等組成唯一的數值;如果單獨連續性也很簡單,但要滿足二者,我們採取把產生seqence的服務單獨獨立出來,寫一個單獨產生唯一、連續id的伺服器,這樣每次去訪問他就好;但每次的改進、解決問題都會引入其他的問題;比如這個服務的穩定性、容錯性4.2.3 多機資料查詢的問題(join)
- 如果垂直分庫後,查詢的多張table 還在一個DB(Data Base) ,可以藉助DB的DBMS 提供的join 功能可以簡單的進行資料的join 動作進行查詢是資料;如果查詢的table 不在一個數據庫中,而是分佈到多臺機器上;這個就不能簡單的join 動作了;
- 上面的問題解決思路有三種:
4.2.4 跨庫查詢的問題和解決 【理解真正的分庫、分表】
- 資料庫分庫分表的演化
從上圖可以看出來,最初使用者資訊儲存在一個數據庫中(最左邊的),然後進行了分庫,變成了2個數據庫(中間的部分),這2個數據庫儲存的使用者資訊是不同的,一般按照使用者id分成2個db,2個數據庫的使用者資訊表加起來相當於最初的使用者資訊表;因為在一個數據庫裡面使用者資訊的表還是非常大,所以要按照一定的規則把使用者資訊的分到2個table裡面,這樣2個數據庫裡面就用了4張使用者資訊的表;這4張表加起來相當於最左邊的使用者資訊表。
- 從邏輯概念上使用者的資訊應該放到一張表中,但是隨著使用者資訊量的增大、訪問量的上升,需要經歷分庫、分表;此時使用者的資訊會分佈到多個數據庫的多張表中;也就是一張邏輯上的表對應了多張物理上的表。那在應用中對張邏輯表的查詢就需要做跨庫跨表的合併了。
- 跨庫跨表的解決方案
- 排序:根據需要進行所有結果資料的排序
- 函式處理:各種max min sum avg 處理
- 業務邏輯的處理
- 分頁排序的問題【資料很多,在不同的頁面顯示;要進行分頁、排序】;也會出現統一排序後然後分頁
4.3 資料訪問層的設計和實現
資料訪問層就是方便應用進行資料讀/寫訪問的抽象層,我們在這個層上解決各個應用通用的訪問資料庫的問題;在分散式系統中,我們把資料訪問層叫做分散式資料訪問層,簡稱為資料層4.3.1 如何對外提供資料訪問層的功能
在java 應用中一般是通過JDBC 方式來訪問資料庫,資料層自身可以作為一個JDBC 的實現,也就是暴露出JDBC的介面給應用;這時應用遷移到分散式資料層的成本就很低了,和使用遠端資料庫的JDBC的驅動方式是一樣的,遷移成本也非常低。我們們採用在JDBC上面包裝一層可以讓應用方便、快捷、低成本的分散式資料訪問層4.3.2 安裝資料層流程的順序看資料層的設計
我們在執行資料庫(分散式)操作時的流程如下: SQL 解析 ---> SQL 規則處理(根據資料的分庫分表地址) ----> SQL 改寫(分解成直接訪問資料庫的多個sql 語句) -----> 資料來源選擇(選擇每一個sql的資料來源) ---->SQL 執行 -----> 查詢結果返回併合並處理;- SQL 解析 ---> 獲取這sql 要查詢的表名資訊
- 規則處理 ---> 根據表名查詢到表所在的資料來源
- 改寫SQL --> 修改表名和資訊
- 選擇資料來源 --> 確定資料來源
- 執行SQL 和結果處理階段
4.4 獨立部署的資料訪問層的實現方式
資料訪問層(上面5個步驟)是作為一個整體向app 提供資料訪問的服務,對應用層應該是透明的;比如使用者表一個邏輯表可能分庫分表後分成多個數據庫多個物理表,但是的應用來說,不用關心裡面的細節,還是把使用者表作為一張表來寫程式即可。至於怎麼從一張邏輯表對映到多張物理表、SQL 的解析、處理、改寫、執行都是資料層完成的工作,對應用來說是透明的[mongodb 本就是把資料訪問層給做到資料裡面,僅僅通過配置就可以實現分庫分表],下面的圖就是資料訪問層的示意圖:4.5 資料庫讀寫分離的挑戰和應對
隨著資料量的增大(一臺機器的磁碟當不下),DB 訪問量增大,導致資料庫壓力很大;一般對一個DB裡說,讀的次數遠遠大於寫的次數,而且讀不會改動DB的資料,跟寫的工作有明顯的區別,所以我們一般就是讀寫分離,就形成了典型的主從分離(讀寫分離): 主庫可寫、可讀,從庫只能讀。
資料讀寫分離後,資料的同步問題就變得非常重要的一個功能了,如果資料不能實時同步會造成讀取資料不是最新的,會造成使用者體驗差或者影響業務的問題;此時我們需要做的就是資料同步。
- 主從資料庫結構一致:採用訊息機制更新從資料庫 [訊息機制不是非常友好,最友好的是根據DB的變更日誌進行跟新資料]
- 主從資料結構不一致: 從庫根據不同的緯度進行分庫
主庫是買家id 的取模進行分庫,這樣查詢買家資料就可以在一個數據庫裡面查詢,但是賣家查詢就需要在所有的資料都查詢一遍,成本會比較高,所以從庫採用賣家的id取模進行分庫,這樣賣家查詢就可以查詢一個庫
- 引入資料變更平臺
- 資料的平滑遷移