基於 EntityFramework 的資料庫主從讀寫分離服務外掛
1. 版本資訊和原始碼
1.1 版本資訊
v1.01 beta(2015-04-07),基於 EF 6.1 開發,支援 EF 6.1 之後的所有 EF6 版本。
1.2 開放原始碼地址
關於該 EF 資料庫主從讀寫分離服務核心原始碼位於資料夾:src\ NDF.Data.EntityFramework\MasterSlaves 資料夾中。
2. 功能概述
2.1 支援在基於 EF6 進行資料操作時:
2.1.1 針對所有的資料寫入操作,自動將請求轉發至 主伺服器(Master,即寫入操作伺服器);
2.1.2 針對所有的資料查詢操作,自動將請求轉發至 從伺服器(Slave ,即查詢操作伺服器);
2.1.3 以上的資料庫操作請求轉發通過在執行命令前更改資料庫連線字串來完成,但是該資料連線字串的更改動作,不需要業務開發人員改動任何現有程式碼;
2.2 在將讀寫命令請求轉發至相應資料庫伺服器時,支援一主多從管理
即可以設定一臺資料庫伺服器作為 Master 伺服器,同時可以設定一臺或者多臺資料庫伺服器作為 Slave 伺服器;
注:Master 伺服器和 Slave 伺服器之間的需提前建立資料同步機制,該部分工作可通過配置 DBMS 系統來完成。
2.3 支援自動檢測伺服器執行狀態:
2.3.1 可自動檢測 Master 伺服器的線上狀態;
2.3.2 可自動檢測設定的 Slave 伺服器列表中每臺 Slave 伺服器節點的線上狀態;
2.3.3 可自定義設定自動檢測伺服器狀態的時間頻率;
2.4 支援在 Slave 伺服器節點不可用時自動切換至 Master 節點:
如果設定了多臺 Slave 伺服器節點,將在每次執行查詢操作時,根據自動檢測的 Slave 伺服器線上狀態自動選擇可用的伺服器節點;如果所有的 Slave 都不可用,則可以根據配置確定是否自動將資料查詢操作切換至 Master 伺服器;
2.5 支援在 Master 伺服器節點不可用時自動切換至 Slave 節點:
在基於 EF6 的資料更改操作時,如果檢測到 Master 伺服器狀態不可用,則可以根據配置確定是否自動將資料更改操作切換至 Slave 伺服器列表中的第一個可用項(一般情況下不建議進行該設定,因為將 Slave 伺服器作為 Master 伺服器使用雖然能使在 Master 故障後應用程式不離線,但是同樣也會帶來在 Slave 伺服器節點之間的資料一致性問題。);
2.6 支援多臺 Slave 節點之間的負載均衡:
如果設定了多臺 Slave 伺服器節點,在每次執行查詢操作時,支援按照設定順序選擇第一臺可用的 Slave 伺服器,也支援隨機選擇所有可用的 Slave 伺服器中任意一臺(該設定可以有效分散 Slave 伺服器查詢壓力)以執行查詢命令。
2.7 支援面向切面的 EF 資料庫主從讀寫分離服務動作攔截器配置:
可通過定義和註冊實現介面 IMasterSlaveInterceptor 的攔截器,以實現在 EF 資料庫主從讀寫分離服務執行特定動作:
掃描伺服器節點可用狀態前、掃描伺服器節點可用狀態後、修改資料庫操作命令的連線字串前、修改資料庫操作命令的連線字串後時以執行使用者指定的附加動作(例如在掃描到伺服器節點不可用時自動記錄日誌或傳送訊息通知)。
2.8 支援 EF 中的多 DbContext 型別配置:
如果專案中使用多種型別的 EF 實體上下文(System.Data.Entity.DbContext) 物件,支援為每個不同型別的 DbContext 分別配置不同的主從讀寫分離資料庫連線方案;
2.9 支援 Master 伺服器節點和 Slave 伺服器節點的熱插拔配置:
即可以不用停止專案的執行,直接通過修改配置檔案 ef.masterslave.config 中的內容,來達到自動重新整理相關配置連線的效果;在修改配置檔案後並重新生效時,支援自定義的更改事件通知。
3. 使用說明
3.1 設定多個數據庫伺服器例項之間的自動同步
首選通過資料庫管理系統(DBMS)來配置多個數據庫伺服器例項之間的主從自動同步機制,例如:
3.1.1 如果是用 MSSQLSERVER 資料庫系統,可以配置多臺資料庫伺服器例項之間的複製、訂閱策略;
3.1.2 如果是用 MySQL 資料庫系統,可以配置多臺資料庫伺服器例項之間的主從複製策略;
3.1.3 其他 Oracle、DB2...
3.2 在專案中新增配置檔案
在專案根目錄下新增配置檔案 ef.masterslave.config,並按規則修改其中的內容,以下是一份參考的配置方式:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="ef.masterslave" type="NDF.Data.Entity.MasterSlaves.ConfigFile.EFMasterSlaveSection, NDF.Data.Entity" requirePermission="false" />
</configSections>
<ef.masterslave>
<!-- 以下是為所有用 EF 實體上下文(DbContext)型別為 MyProject.Data.MyDbContext 的資料庫操作配置主從讀寫分離服務 -->
<applyItem targetContext="Model.TDHShowEntities, Model"
autoSwitchSlaveOnMasterFauled="false" autoSwitchMasterOnSlavesFauled="true"
serverStateScanInterval="60" serverStateScanWithNonOffline="false"
slaveRandomization="true" >
<master connectionString="data source=192.168.1.1;initial catalog=TDHShow;user id=sa;password=sa;multipleactiveresultsets=True;application name=EntityFramework" />
<slaves>
<add connectionString="data source=192.168.1.2;initial catalog=TDHShow;user id=sa;password=sa;multipleactiveresultsets=True;application name=EntityFramework" order="0" />
</slaves>
</applyItem>
<!-- 以下是為另一個 EF 實體上下文(DbContext)配置主從讀寫分離服務 -->
<!--<applyItem ...>
<master ... />
<slaves>
<add ... />
<add ... />
</slaves>
</applyItem>-->
</ef.masterslave>
</configuration>
3.3 在專案中引入依賴的程式包
3.3.1 EntityFramework 6.1 以上版本;
3.3.2 Microsoft Enterprise Library - Data Access Application Block 6;
3.3.3 Newtonsoft.Json.dll 6.0 以上版本;
3.3.4 NDF.Utilities.dll;
3.3.5 NDF.Data.dll;
3.3.6 NDF.Data.EntityFramework.dll;
3.4 在專案中新增啟動程式碼
在專案的啟動程式碼中(控制檯和桌面程式一般為 Program 型別的 Main 方法、ASP.NET 程式一般為 Global.asax 檔案的 Application_Start 程式碼塊)加入如下程式碼段:
NDF.Data.Entity.MasterSlaves.EFMasterSlaveConfig.Register(typeof(Model.TDHShowEntities));
其中方法中傳入的型別引數應該是 ef.masterslave.config 配置檔案中 applyItem 節的 targetContext 屬性所示的型別,表示要為具體哪個型別的 EF 實體上下文(DbContext) 配置讀寫分離服務。
4. 其他
4.1 關於主從資料庫中相關資料內容的自動同步機制,由資料庫管理系統(DBMS,如 MSSQLSERVER、Oracle、MySQL、DB2 等)來完成,該部分的功能不由本外掛來提供;目前幾乎所有的主流 DBMS 系統都提供了主從資料庫自動同步機制相關功能;
4.2 該 EF 資料庫主從讀寫分離方案支援所有普通資料庫事務和分散式事務操作,不過分散式事務也同樣需要資料庫管理系統(DBMS)的支援否則無效;
4.3 在基於 EF6 和該外掛的配合進行資料庫主從讀寫分離操作,程式會自動檢測所執行的資料庫操作的事務狀態,並自動將帶有資料庫事務或分散式事務的所有 增刪改請求 和 查詢請求 都轉發至 Master 伺服器。
4.4 本篇文章只是概述性的介紹了本人編寫的這個 EF 資料庫主從讀寫分離外掛,關於該外掛的原始碼實現原理和思路,本人將會在以後的博文中展開介紹。