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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

ShardingCore 如何呈现“完美”分表

發布時間:2023/12/4 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ShardingCore 如何呈现“完美”分表 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  這篇文章是我針對efcore的分表的簡單介紹,如果您有以下需求那么可以自己選擇是否使用本框架,本框架將一直持續更新下去,并且免費開源為.net生態做貢獻,如果您覺得不錯那么請幫忙點個star謝謝,框架地址[`sharding-core`](https://github.com/xuejmnet/sharding-core) 您的支持是對我最大的動力。

如果您對分表有以下痛點那么不妨試試我這邊開源的框架sharding-core?,是否需要無感知使用分表組件,是否需要支持abp,是否需要支持自定義分表規則,是否需要支持自定義分表鍵,是否需要支持特定的efcore版本,是否希望框架不帶任何三方框架干凈,是否需要支持讀寫分離,是否需要動態添加表,是否需要支持join,group等操作,是否需要支持追蹤特性,是否想在不修改原先代碼的基礎上擴展分表功能,如果一起上幾個條件任意組合且你在市面上沒辦法找到可替代的框架可以試試本框架。如何使用代碼具體可以參考github 將代碼下載下來如果本地裝了sqlserver直接運行單元測試或者Sample.SqlServer程序會自動在本地新建數據庫新建數據庫表結構,目前初始化數據為用戶信息和用戶對應的月薪信息表,用戶表以用戶id取模,用戶月薪表以月份分表。

首先需要了解本框架的一個版本號不然將對您的使用產生一定的分歧,目前框架分為3個版本分別是2.x,3.x,5.x3個版本,分別對應efcore 2.x efcore 3.x efcore 5.x,有人要問為什么不支持6.x呢(小弟剛剛在上周完成對本框架的開發重構,目前還未對efcore 6.x進行著手不過將在不遠的將來即將支持(目測1-2個星期內))。

目前efcore生態下有著許許多多的分表、分庫的解決方案,但是目前來講都有其不足點,比如需要手動設置分表后綴、需要大量替換現有代碼、不支持事務等等一系列問題,所以在這個大前提下我之前開源了sharding-core?分表組件,這個分表組件是目前來說個人認為比較“完美”的分表組件,這個分表組件目前是參考了sharding-jdbc來實現的,但是比sharding-jdbc更加強大(因為C#的表達式)。首先我們來看下目前市面上有的分表組件的缺點我們來針對其缺點進行痛點解決。

efcore支持情況

efcore版本是否支持
2.x支持
3.x支持
5.x支持
6.x即將支持

數據庫支持情況

數據庫理論是否支持
SqlServer支持
MySql支持
PostgreSql支持
SQLite支持
Oracle支持
其他支持(只要efcore支持)

理論上只要是efcore對應版本支持的數據庫,sharding-core都將支持。

如何開始使用

1.創建一個數據庫對象繼承IShardingTable并且在對應的分表字段上進行[ShardingTableKey]特性的標注

/// <summary>/// 用戶表/// </summary>public class SysUserMod : IShardingTable{/// <summary>/// 用戶Id用于分表/// </summary>[ShardingTableKey(TailPrefix = "_")]public string Id { get; set; }/// <summary>/// 用戶名稱/// </summary>public string Name { get; set; }/// <summary>/// 用戶姓名/// </summary>public int Age { get; set; }}

2.創建對應的實體表對應配置 推薦?fluent api

public class SysTestMap:IEntityTypeConfiguration<SysTest>{public void Configure(EntityTypeBuilder<SysTest> builder){builder.HasKey(o => o.Id);builder.Property(o => o.Id).IsRequired().HasMaxLength(128);builder.Property(o => o.UserId).IsRequired().HasMaxLength(128);builder.ToTable(nameof(SysTest));}}

3.創建對應的分表規則 取模分表,參數2代表后綴2位就是00-99最多100張表,3表示模3== key.hashcode() %3

public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute<SysUserMod>{public SysUserModVirtualTableRoute() : base(2,3){}}

4創建對應執行的dbcontext 這一步除了繼承IShardingTableDbContext外其他和普通dbcontext一樣

public class DefaultTableDbContext: DbContext,IShardingTableDbContext{public DefaultTableDbContext(DbContextOptions<DefaultTableDbContext> options) :base(options){}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfiguration(new SysUserModMap());}public IRouteTail RouteTail { get; set; }}

5.添加分表dbcontext

public class DefaultShardingDbContext:AbstractShardingDbContext<DefaultTableDbContext>{public DefaultShardingDbContext(DbContextOptions<DefaultShardingDbContext> options) : base(options){}protected override void OnModelCreating(ModelBuilder modelBuilder){base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfiguration(new SysUserModMap());}public override Type ShardingDbContextType => this.GetType();}

6.添加配置

public void ConfigureServices(IServiceCollection services){services.AddControllers();//原先的dbcontext可以用也可以不用如果原先的dbcontext還在用就繼續//services.AddDbContext<DefaultTableDbContext>(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx3;Integrated Security=True"));services.AddShardingDbContext<DefaultShardingDbContext, DefaultTableDbContext>(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBxx2;Integrated Security=True;"), op =>{op.EnsureCreatedWithOutShardingTable = true;op.CreateShardingTableOnStart = true;op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),//使用dbconnection創建dbcontext支持事務(conStr,builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger));//使用鏈接字符串創建dbcontextop.AddShardingTableRoute<SysUserModVirtualTableRoute>();});}public void Configure(IApplicationBuilder app, IWebHostEnvironment env){...//添加啟動項app.UseShardingCore();...}public static class ShardingCoreExtension{public static IApplicationBuilder UseShardingCore(this IApplicationBuilder app){var shardingBootstrapper = app.ApplicationServices.GetRequiredService<IShardingBootstrapper>();shardingBootstrapper.Start();return app;}}

7.控制器使用

private readonly DefaultShardingDbContext _defaultTableDbContext;public ValuesController(DefaultShardingDbContext defaultTableDbContext){_defaultTableDbContext = defaultTableDbContext;}[HttpGet]public async Task<IActionResult> Get(){var resultx11231 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Age == 198198).Select(o=>o.Id).ContainsAsync("1981");var resultx1121 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").SumAsync(o=>o.Age);var resultx111 = await _defaultTableDbContext.Set<SysUserMod>().FirstOrDefaultAsync(o => o.Id == "198");var resultx2 = await _defaultTableDbContext.Set<SysUserMod>().CountAsync(o => o.Age<=10);var resultx = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").FirstOrDefaultAsync();var resultx33 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").Select(o=>o.Id).FirstOrDefaultAsync();var resulxxt = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").ToListAsync();var result = await _defaultTableDbContext.Set<SysUserMod>().ToListAsync();var sysUserMod98 = result.FirstOrDefault(o => o.Id == "98");_defaultTableDbContext.Attach(sysUserMod98);sysUserMod98.Name = "name_update"+new Random().Next(1,99)+"_98";await _defaultTableDbContext.SaveChangesAsync();return Ok(result);}

自定義分表鍵,自定義分表規則

目前市面上有的框架要么對分表字段有限制比如僅支持DateTime類型或者int等,要么對分表規則有限制:僅支持按天、按月、取模...等等,但是基于分表規則和分表字段是業務規則所以本框架遵循將其由業務系統自己定義,最大化來實現分表庫的適用性,基本上滿足一切分表規則,且sharding-core目前默認提供一些常用的分表規則可以快速集成。

默認路由

抽象abstract路由規則tail索引
AbstractSimpleShardingModKeyIntVirtualTableRoute取模0,1,2...=
AbstractSimpleShardingModKeyStringVirtualTableRoute取模0,1,2...=
AbstractSimpleShardingDayKeyDateTimeVirtualTableRoute按時間yyyyMMdd>,>=,<,<=,=,contains
AbstractSimpleShardingDayKeyLongVirtualTableRoute按時間戳yyyyMMdd>,>=,<,<=,=,contains
AbstractSimpleShardingWeekKeyDateTimeVirtualTableRoute按時間yyyyMMdd_dd>,>=,<,<=,=,contains
AbstractSimpleShardingWeekKeyLongVirtualTableRoute按時間戳yyyyMMdd_dd>,>=,<,<=,=,contains
AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute按時間yyyyMM>,>=,<,<=,=,contains
AbstractSimpleShardingMonthKeyLongVirtualTableRoute按時間戳yyyyMM>,>=,<,<=,=,contains
AbstractSimpleShardingYearKeyDateTimeVirtualTableRoute按時間yyyy>,>=,<,<=,=,contains
AbstractSimpleShardingYearKeyLongVirtualTableRoute按時間戳yyyy>,>=,<,<=,=,contains

所謂的索引就是通過改對應的條件操作符可以縮小減少指定表的范圍,加快程序的執行
如果以上默認分表無法滿足您的需求您還可以自定義分表,如何分表可以通過繼承 AbstractShardingOperatorVirtualTableRoute<TEntity,TKey>來實現自定義分表規則(近乎90%的規則都可以實現)

動態添加分表信息

很多分表組件默認不帶動態分表信息導致很多分表沒辦法根據業務系統來進行動態創建,sharding-core默認提供動態建表接口可以支持動態按時間,按租戶等不需要數據做遷移的動態分表信息,
如果需要請參考Samples.AutoByDate.SqlServer

支持select,join,group by等連表聚合函數

目前sharding-core支持select按需查詢,join分表連表查詢,group by聚合查詢,雖然本框架支持但是出于性能原因本框架還是不建議使用join操作符來操作,因為過多的表路由會導致笛卡爾積,會導致需要查詢的表集合增長對數據庫連接比較考驗。
以下代碼來自github的單元測試中,SysUserMod表示用戶表,SysUserSalary表示用戶月薪表用戶表按id取模,用戶月薪表按月分表

//join查詢 var list = await (from u in _virtualDbContext.Set<SysUserMod>()join salary in _virtualDbContext.Set<SysUserSalary>()on u.Id equals salary.UserIdselect new{u.Id,u.Age,Salary = salary.Salary,DateOfMonth = salary.DateOfMonth,Name = u.Name}).ToListAsync();//group聚合查詢 var ids = new[] {"200", "300"};var dateOfMonths = new[] {202111, 202110};var group = await (from u in _virtualDbContext.Set<SysUserSalary>().Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))group u by new{UId = u.UserId}into gselect new{GroupUserId = g.Key.UId,Count = g.Count(),TotalSalary = g.Sum(o => o.Salary),AvgSalary = g.Average(o => o.Salary),AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),MinSalary = g.Min(o => o.Salary),MaxSalary = g.Max(o => o.Salary)}).ToListAsync();

分頁

我們常說的分頁是分表的難點也是最考驗分表組件的
1我們首先來看普通的分表組件如何分頁
首先我們定義一組組數據比如是1-100的連續數字,然后分成兩張表按奇偶分表

表名數據
table11,3,5,7,9...
table22,4,6,8,10...
select * from table limit 2,2理論上結果3,4 如果本次查詢會做落到table1 和table2那么會改寫成 2句sql 第一句 select * from table1 limit 4 ---> 1,3,5,7 第二句 select * from table2 limit 4 ---> 2,4,6,8 將8條數據放入內存然后排序 1,2,3,4,5,6,7,8 獲取第3到4條數據 結果[3,4]

這個情況是我們常見的也是最簡單的分頁,但是這個情況僅僅適用于數據量小的時候,如果用戶不小心點到了分頁的最后一頁那么結果將是災難性的這是毋庸置疑的
那么sharding-core是如何處理的呢

select * from table limit 2,2 首先還是一樣對數據庫語句進行改性并且生成對應的sql 第一句 select * from table1 limit 4 第二句 select * from table2 limit 4 因為ado.net默認DataReader是流式獲取,只要連接不關閉那么可以一直實現next獲取到內存 創建一個優先級隊列一個可以具有排序功能的隊列 因為DataReader的特性我們分別對sql1和sql2進行一次next獲取到2個數組一個是[1,.....] A和數組[2......] B 獲取到兩個數組我們只知道頭部第一個對象因為沒有進行后續的next所以無法知曉剩下的數據但是有一點可以知道后面的數據都是按sql的指定順序的所以都不會比當前頭大或者小 先將1和2放入優先級隊列可以知道如果asc那么數組A放在隊列頭 數組B放在隊列尾部,然后對優先級隊列進行poll彈出,并且對A進行next這個時候A變成了[3,....]再將A放入優先級隊列 這時候優先級隊列就是B在前A在后依次操作,然后對分頁的進行過濾因為要跳過2個對象所以只需要空執行2次那么指針就會指向A數組的3和B數組的4,剩下的只要獲取2個數據就可以了, 這樣做可以保證內存最小化,然后分頁不會成為程序的災難。

無感知使用

目前的分表框架很少有做到無感知使用的,你在使用的時候好一點的框架不依賴三方,一般一點的不但要依賴很多三方框架并且在使用的時候還有一大堆限制,必須使用他的東西還沒辦法做到和dbcontext原生的使用方法。
sharding-core目前使用的是一種類似dbcontext的wrap模式,用一個新的dbcontext來包裝真實的dbcontext,這個包裝的dbcontext我們成為shardingdbcontext,shardingDbContext因為本身也是集成于DbContext所以它的使用方法和原生dbcontext沒有差別。并且僅需少量改動即可支持abp和abp.next

讀寫分離的支持

目前sharding-core已經支持單node節點的讀寫分離操作,將在不久的未來(1-2)天內支持多節點的讀寫分離

services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]),op =>{op.EnsureCreatedWithOutShardingTable = true;op.CreateShardingTableOnStart = true;op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),(conStr,builder)=> builder.UseSqlServer("read db connection string").UseLoggerFactory(efLogger));op.AddShardingTableRoute<SysUserModVirtualTableRoute>();op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();});

未來計劃將支持分庫,支持強制路由,顯示路由等...
最后具體如何使用且使用方式可以參考github(https://github.com/xuejmnet/sharding-core) 當然我也會在后續出一系列的博客來對框架進行支持的介紹

最后的最后

該文檔是我晚上趕工趕出來的也想趁熱打鐵希望更多的人關注,也希望更多的人可以交流。

憑借各大開源生態圈提供的優秀代碼和思路才有的這個框架,希望可以為.Net生態提供一份微薄之力,該框架本人會一直長期維護,有大神技術支持可以聯系下方方式歡迎star ????

博客

QQ群:771630778

個人QQ:326308290(歡迎技術支持提供您寶貴的意見)

個人郵箱:326308290@qq.com

總結

以上是生活随笔為你收集整理的ShardingCore 如何呈现“完美”分表的全部內容,希望文章能夠幫你解決所遇到的問題。

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