基於 EntityFramework 的數據庫主從讀寫分離服務插件
1. 版本信息和源碼
1.1 版本信息
v1.01 beta(2015-04-07),基於 EF 6.1 開發,支持 EF 6.1 之后的所有 EF6 版本。
1.2 開放源碼地址
https://github.com/cjw0511/NDF.Infrastructure
關於該 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,並按規則修改其中的內容,以下是一份參考的配置方式:
1 <?xml version="1.0" encoding="utf-8" ?> 2 3 <configuration> 4 5 <configSections> 6 7 <section name="ef.masterslave" type="NDF.Data.EntityFramework.MasterSlaves.ConfigFile.EFMasterSlaveSection, NDF.Data.EntityFramework" 8 9 requirePermission="false" /> 10 11 </configSections> 12 13 <ef.masterslave> 14 15 <!-- 以下是為所有用 EF 實體上下文(DbContext)類型為 MyProject.Data.MyDbContext 的數據庫操作配置主從讀寫分離服務 --> 16 17 <applyItem targetContext="MyProject.Data.MyDbContext, MyProject.Data" 18 19 autoSwitchSlaveOnMasterFauled="false" autoSwitchMasterOnSlavesFauled="true" 20 21 serverStateScanInterval="60" serverStateScanWithNoOffline="false" 22 23 slaveRandomization="true" > 24 25 <master connectionString="server=192.168.0.99;port=3306;user id=root;password=123456;persistsecurityinfo=True;database=testdb;convertzerodatetime=True;allowzerodatetime=True" /> 26 27 <slaves> 28 29 <add connectionString="server=192.168.0.101;port=3306;user id=root;password=123456;persistsecurityinfo=True;database=testdb;convertzerodatetime=True;allowzerodatetime=True" order="0" /> 30 31 <add connectionString="server=192.168.0.102;port=3306;user id=root;password=123456;persistsecurityinfo=True;database=testdb;convertzerodatetime=True;allowzerodatetime=True" order="1" /> 32 33 <add connectionString="server=192.168.0.103;port=3306;user id=root;password=123456;persistsecurityinfo=True;database=testdb;convertzerodatetime=True;allowzerodatetime=True" order="2" /> 34 35 </slaves> 36 37 </applyItem> 38 39 <!-- 以下是為另一個 EF 實體上下文(DbContext)配置主從讀寫分離服務 --> 40 41 <!--<applyItem ...> 42 43 <master ... /> 44 45 <slaves> 46 47 <add ... /> 48 49 <add ... /> 50 51 </slaves> 52 53 </applyItem>--> 54 55 </ef.masterslave> 56 57 </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 代碼塊)加入如下代碼段:
1 NDF.Data.EntityFramework.MasterSlaves.EFMasterSlaveConfig.Register(typeof(MyDbContext));
其中方法中傳入的類型參數應該是 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 數據庫主從讀寫分離插件,關於該插件的源碼實現原理和思路,本人將會在以后的博文中展開介紹。
