日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

EFCore.Sharding(EFCore开源分表框架)

發布時間:2023/12/4 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 EFCore.Sharding(EFCore开源分表框架) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介

本框架旨在為EF Core提供Sharding(即讀寫分離分庫分表)支持,不僅提供了一套強大的普通數據操作接口,并且降低了分表難度,支持按時間自動分表擴容,提供的操作接口簡潔統一.

源碼地址:EFCore.SHarding

引言

讀寫分離分庫分表一直是數據庫領域中的重難點,當數據規模達到單庫極限的時候,就不得不考慮分表方案。EF Core作為.NET Core中最為主流的ORM,用起來十分方便快捷,但是官方并沒有相應的Sharding支持,鄙人不才,經過一番摸索之后終于完成這個框架.

開始

準備

首先根據需要安裝對應的Nuget包

包名說明
EFCore.Sharding必裝包,3.x版本對應EF Core3.x,2.x版本對應EF Core2.x
EFCore.Sharding.MySqlMySql支持
EFCore.Sharding.PostgreSqlPostgreSql支持
EFCore.Sharding.SQLiteSQLite支持
EFCore.Sharding.SqlServerSqlServer支持
EFCore.Sharding.OracleOracle支持(暫不支持3.x)

配置

class Base_UnitTestShardingRule : ModShardingRule<Base_UnitTest> {protected override string KeyField => "Id";protected override int Mod => 3; }ShardingConfig.Init(config => {config.AddAbsDb(DatabaseType.SQLite).AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, "DataSource=db.db").AddPhysicDbGroup().AddPhysicTable<Base_UnitTest>("Base_UnitTest_0").AddPhysicTable<Base_UnitTest>("Base_UnitTest_1").AddPhysicTable<Base_UnitTest>("Base_UnitTest_2").SetShardingRule(new Base_UnitTestShardingRule()); });

上述代碼中完成了Sharding配置

  • AddAbsDb是指添加抽象數據庫,抽象數據庫就是將多個分庫看成同一個數據庫來進行操作

  • AddPhysicDbGroup是指添加物理數據庫組,在同一組物理數據庫中,它們數據庫類型相同,擁有的表相同,每個數據庫擁有的數據是一致的(之間通過主主復制或主從復制進行數據同步)

  • AddPhysicTable是指添加物理數據表,傳入的Base_UnitTest是抽象數據表(即將Base_UnitTest拆分為Base_UnitTest_0~2)

  • Base_UnitTestShardingRule是采用的分表規則,上述代碼中采用的是哈希取模的分表方式

使用

配置完成,下面開始使用,使用方式非常簡單,與平常使用基本一致
首先獲取分片倉儲接口IShardingRepository

IShardingRepository _db = DbFactory.GetRepository().ToSharding();

然后即可進行數據操作:

Base_UnitTest _newData = new Base_UnitTest {Id = Guid.NewGuid().ToString(),UserId = "Admin",UserName = "超級管理員",Age = 22 }; List<Base_UnitTest> _insertList = new List<Base_UnitTest> {new Base_UnitTest{Id = Guid.NewGuid().ToString(),UserId = "Admin1",UserName = "超級管理員1",Age = 22},new Base_UnitTest{Id = Guid.NewGuid().ToString(),UserId = "Admin2",UserName = "超級管理員2",Age = 22} }; //添加單條數據 _db.Insert(_newData); //添加多條數據 _db.Insert(_insertList); //清空表 _db.DeleteAll<Base_UnitTest>(); //刪除單條數據 _db.Delete(_newData); //刪除多條數據 _db.Delete(_insertList); //刪除指定數據 _db.Delete<Base_UnitTest>(x => x.UserId == "Admin2"); //更新單條數據 _db.Update(_newData); //更新多條數據 _db.Update(_insertList); //更新單條數據指定屬性 _db.UpdateAny(_newData, new List<string> { "UserName", "Age" }); //更新多條數據指定屬性 _db.UpdateAny(_insertList, new List<string> { "UserName", "Age" }); //更新指定條件數據 _db.UpdateWhere<Base_UnitTest>(x => x.UserId == "Admin", x => {x.UserId = "Admin2"; }); //GetList獲取表的所有數據 var list=_db.GetList<Base_UnitTest>(); //GetIQPagination獲取分頁后的數據 var list=_db.GetIShardingQueryable<Base_UnitTest>().GetPagination(pagination); //Max var max=_db.GetIShardingQueryable<Base_UnitTest>().Max(x => x.Age); //Min var min=_db.GetIShardingQueryable<Base_UnitTest>().Min(x => x.Age); //Average var min=_db.GetIShardingQueryable<Base_UnitTest>().Average(x => x.Age); //Count var min=_db.GetIShardingQueryable<Base_UnitTest>().Count(); //事務,使用方式與普通事務一致 bool succcess = _db.RunTransaction(() => {_db.Insert(_newData);var newData2 = _newData.DeepClone();_db.Insert(newData2); }).Success; Assert.AreEqual(succcess, false);

上述操作中表面上是操作Base_UnitTest表,實際上卻在按照一定規則使用Base_UnitTest_0~2三張表,使分片對業務操作透明,極大提高開發效率
具體使用方式請參考單元測試源碼:連接

按時間自動分表

上面的哈希取模的方式雖然簡單,但是卻十分不實用,因為當3張分表到達瓶頸時,將會面臨擴容的問題,這種方式擴容需要進行大量的數據遷移,這無疑是十分麻煩的。因此需要一種方式能夠系統自動建表擴容,并且無需人工干預,這就是按時間自動分表.

using Demo.Common; using EFCore.Sharding; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks;namespace Demo.AutoExpandByDate {class Base_UnitTestShardingRule : AbsShardingRule<Base_UnitTest>{public override DateTime BuildDate(Base_UnitTest obj){return obj.CreateTime;}}class Program{/// <summary>/// 表都在同一個數據庫中/// </summary>public static void OneGroup(){DateTime startTime = DateTime.Now.AddMinutes(-5);DateTime endTime = DateTime.MaxValue;//配置初始化ShardingConfig.Init(config =>{config.AddAbsDb(DatabaseType.SqlServer)//添加抽象數據庫.AddPhysicDbGroup()//添加物理數據庫組.AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.ConString1)//添加物理數據庫1.SetShardingRule(new Base_UnitTestShardingRule())//設置分表規則.AutoExpandByDate<Base_UnitTest>(//設置為按時間自動分表ExpandByDateMode.PerMinute,(startTime, endTime, ShardingConfig.DefaultDbGourpName));});var db = DbFactory.GetShardingRepository();while (true){db.Insert(new Base_UnitTest{Id = Guid.NewGuid().ToString(),Age = 1,UserName = Guid.NewGuid().ToString(),CreateTime = DateTime.Now});var count = db.GetIShardingQueryable<Base_UnitTest>().Count();Console.WriteLine($"當前數據量:{count}");Thread.Sleep(50);}}/// <summary>/// 表分布在兩個數據庫測試/// </summary>public static void TwoGroup(){DateTime startTime1 = DateTime.Now.AddMinutes(-5);DateTime endTime1 = DateTime.Now.AddMinutes(5);DateTime startTime2 = endTime1;DateTime endTime2 = DateTime.MaxValue;string group1 = "group1";string group2 = "group2";//配置初始化ShardingConfig.Init(config =>{config.AddAbsDb(DatabaseType.SqlServer)//添加抽象數據庫.AddPhysicDbGroup(group1)//添加物理數據庫組1.AddPhysicDbGroup(group2)//添加物理數據庫組2.AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.ConString1, group1)//添加物理數據庫1.AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.ConString2, group2)//添加物理數據庫2.SetShardingRule(new Base_UnitTestShardingRule())//設置分表規則.AutoExpandByDate<Base_UnitTest>(//設置為按時間自動分表ExpandByDateMode.PerMinute,(startTime1, endTime1, group1),(startTime2, endTime2, group2));});List<Task> tasks = new List<Task>();for (int i = 0; i < 4; i++){tasks.Add(Task.Run(() =>{var db = DbFactory.GetShardingRepository();while (true){db.Insert(new Base_UnitTest{Id = Guid.NewGuid().ToString(),Age = 1,UserName = Guid.NewGuid().ToString(),CreateTime = DateTime.Now});var count = db.GetIShardingQueryable<Base_UnitTest>().Count();Console.WriteLine($"當前數據量:{count}");Thread.Sleep(50);}}));}Console.ReadLine();}static void Main(string[] args){OneGroup();Console.ReadLine();}} }

上面Demo都在源碼中

上面的代碼實現了將Base_UnitTest表按照時間自動分表,每分鐘創建一張表,實際使用中根據業務需求設置ExpandByDateMode參數,常用按天、按月分表

自動分表效果

全程無需人工干預,系統會自動定時創建分表,十分簡單好用

性能測試

using Demo.Common; using EFCore.Sharding; using System; using System.Diagnostics; using System.Linq;namespace Demo.Performance {class Base_UnitTestShardingRule : ModShardingRule<Base_UnitTest>{protected override string KeyField => "Id";protected override int Mod => 3;}class Program{static void Main(string[] args){ShardingConfig.Init(config =>{config.AddAbsDb(DatabaseType.SqlServer).AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.ConString1).AddPhysicDbGroup().AddPhysicTable<Base_UnitTest>("Base_UnitTest_0").AddPhysicTable<Base_UnitTest>("Base_UnitTest_1").AddPhysicTable<Base_UnitTest>("Base_UnitTest_2").SetShardingRule(new Base_UnitTestShardingRule());});var db = DbFactory.GetRepository(Config.ConString1, DatabaseType.SqlServer);Stopwatch watch = new Stopwatch();var q = db.GetIQueryable<Base_UnitTest>().Where(x => x.UserName.Contains("00001C22-8DD2-4D47-B500-407554B099AB")).OrderByDescending(x => x.Id).Skip(0).Take(30);q.ToList();q.ToSharding().ToList();watch.Restart();var list1 = q.ToList();watch.Stop();Console.WriteLine($"未分表耗時:{watch.ElapsedMilliseconds}ms");watch.Restart();var list2 = q.ToSharding().ToList();watch.Stop();Console.WriteLine($"分表后耗時:{watch.ElapsedMilliseconds}ms");Console.WriteLine("完成");}} }

分表Base_UnitTest_0-2各有100萬數據,然后將這三張表的數據導入Base_UnitTest中(即Base_UnitTest表的數據與Base_UnitTest_0-2三張表總合數據一致)

分表與不分表測試結果如下

這里僅僅分了3張表,其效果立桿見影,若分表幾十張,那效果想想就很棒

其它簡單操作(非Sharing)

框架不僅支持Sharing,而且封裝了常用數據庫操作,使用比較簡單
詳細使用方式參考?鏈接

總結

這個簡單實用強大的框架希望能夠幫助到大家,力求為.NET生態貢獻一份力,大家一起壯大.NET生態

歡迎使用本框架,若覺得不錯,請比心

Github歡迎星星:https://github.com/Coldairarrow

博客園歡迎點贊:https://www.cnblogs.com/coldairarrow/

QQ群3:940069478
個人QQ:862520575(歡迎技術支持及商務合作,提供.NET Core + Linux + Nginx+ jenkins + git整套持續集成快速開發平臺

總結

以上是生活随笔為你收集整理的EFCore.Sharding(EFCore开源分表框架)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。