ShardingCore

ShardingCore 是一个支持efcore 2.x 3.x 5.x的一个对于数据库分表的一个简易扩展,

目前该库暂未支持分库(未来会支持),仅支持分表,该项目的理念是让你可以已最少的代码量来实现自动分表的实现,经过多个开源项目的摸索参考目前正式开源本项目

项目地址 github 喜欢的朋友可以点下star Thanks♪(・ω・)ノ

依赖

Release EF Core .NET Standard .NET (Core) Sql Server Pomelo.EntityFrameworkCore.MySql
5.x.x.x >= 5.0.x 2.1 3.0+ >= 2012 5.0.0-alpha.2
3.x.x.x 3.1.10 2.0 2.0+ >= 2012 3.2.4
2.x.x.x 2.2.6 2.0 2.0+ >= 2008 2.2.6

开始

以下所有例子都以Sql Server为例 MySql亦如此

简介

目前该库处于初期阶段,有很多bug也希望各位多多理解,一起努力为.net生态做出一份微薄之力,目前该库支持的分页可以进行完全的自定义,基本上可以满足95%以上的

业务需求,唯一的限制就是分表规则必须满足 x+y+z,x表示固定的表名,y表示固定的表名和表后缀之间的联系(可以为空),z表示表后缀,可以按照你自己的任意业务逻辑进行切分,

如:user_0,user_1或者user202101,user202102...当然该库同样适用于多租户模式下的隔离,该库为了支持之后的分库已经重写了之前的union all查询模式,并且支持多种api,

支持多种查询包括join group by max count min avg sum ...等一系列查询,之后可能会添加更多支持,目前该库的使用非常简单,基本上就是针对IQueryable的扩展,为了保证

该库的简介目前仅使用该库无法或者说难以实现自动建表,但是只需要配合定时任务该库即可完成24小时无人看管自动管理。该库提供了 IShardingTableCreator

作为建表的依赖,如果需要可以参考 按天自动建表

概念

本库的几个简单的核心概念:

  • [Tail]

    尾巴、后缀物理表的后缀
  • [TailPrefix]

    尾巴前缀虚拟表和物理表的后缀中间的字符
  • [物理表]

    顾名思义就是数据库对应的实际表信息,表名(tablename+ tailprefix+ tail) IPhysicTable
  • [虚拟表]

    虚拟表就是系统将所有的物理表在系统里面进行抽象的一个总表对应到程序就是一个entityIVirtualTable
  • [虚拟路由]

    虚拟路由就是联系虚拟表和物理表的中间介质,虚拟表在整个程序中只有一份,那么程序如何知道要查询系统哪一张表呢,最简单的方式就是通过虚拟表对应的路由IVirtualRoute

    ,由于基本上所有的路由都是和业务逻辑相关的所以虚拟路由由用户自己实现,该框架提供一个高级抽象

优点

  • [支持自定义分表规则]
  • [支持任意类型分表key]
  • [针对iqueryable的扩展方便使用]
  • [支持分表下的连表] join
  • [支持针对批处理的使用] BulkInsert、BulkUpdate、BulkDelete
  • [提供多种默认分表规则路由] 按时间按取模
  • [针对分页进行优化] 大页数跳转支持低内存流式处理

缺点

  • [暂不支持分库(不久后会支持)]
  • [消耗连接]出现分表与分表对象进行join如果条件没法索引到具体表会生成笛卡尔积导致连接数爆炸,后期会进行针对该情况的配置
  • [该库比较年轻] 可能会有一系列bug或者单元测试不到位的情况,但是只要你在群里或者提了issues我会尽快解决

安装

<PackageReference Include="ShardingCore.SqlServer" Version="5.0.0.3" />

配置

配置entity 推荐 fluent api 可以实现自动建表功能

IShardingEntity数据库对象必须继承该接口

ShardingKey分表字段需要使用该特性

    public class SysUserMod:IShardingEntity
{
/// <summary>
/// 用户Id用于分表
/// </summary>
[ShardingKey]
public string Id { get; set; }
/// <summary>
/// 用户名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 用户姓名
/// </summary>
public int Age { get; set; }
} public class SysUserModMap:IEntityTypeConfiguration<SysUserMod>
{
public void Configure(EntityTypeBuilder<SysUserMod> builder)
{
builder.HasKey(o => o.Id);
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
builder.Property(o => o.Name).HasMaxLength(128);
builder.ToTable(nameof(SysUserMod));
}
}

创建virtual route

实现 AbstractShardingOperatorVirtualRoute<T, TKey>

抽象,或者实现系统默认的虚拟路由

框架默认有提供几个简单的路由 默认路由


public class SysUserModVirtualRoute : AbstractSimpleShardingModKeyStringVirtualRoute<SysUserMod>
{
public SysUserModVirtualRoute() : base(3)
{
}
public override List<string> GetAllTails()
{
return new() { "0","1","2"};
}
}
  • GetAllTails

    现在数据库已存在的尾巴有哪些

Startup.cs 下的 ConfigureServices(IServiceCollection services)


services.AddShardingSqlServer(o =>
{
o.ConnectionString = "";
o.AddSharding<SysUserModVirtualRoute>();
o.UseShardingCoreConfig((provider, config) =>
{
//如果是development就判断并且新建数据库如果不存在的话(ishardingentity不会被创建)
config.EnsureCreated = provider.GetService<IHostEnvironment>().IsDevelopment();
//ishardingentity表是否需要在启动时创建(如果已创建可以选择不创建)
config.CreateShardingTableOnStart = true;
});
});

Startup.cs 下的 Configure(IApplicationBuilder app, IWebHostEnvironment env) 你也可以自行封装app.UseShardingCore()


var shardingBootstrapper = app.ApplicationServices.GetRequiredService<IShardingBootstrapper>();
shardingBootstrapper.Start();

使用


private readonly IVirtualDbContext _virtualDbContext; public ctor(IVirtualDbContext virtualDbContext)
{
_virtualDbContext = virtualDbContext;
} public async Task ToList_All()
{
//查询list集合
var all=await _virtualDbContext.Set<SysUserMod>().ToShardingListAsync();
//链接查询
var list = await (from u in _virtualDbContext.Set<SysUserMod>()
join salary in _virtualDbContext.Set<SysUserSalary>()
on u.Id equals salary.UserId
select new
{
Salary = salary.Salary,
DateOfMonth = salary.DateOfMonth,
Name = u.Name
}).ToShardingListAsync();
//聚合查询
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 g
select new
{
GroupUserId = g.Key.UId,
Count = g.Count(),
TotalSalary = g.Sum(o => o.Salary),
AvgSalary = g.Average(o => o.Salary),
MinSalary = g.Min(o => o.Salary),
MaxSalary = g.Max(o => o.Salary)
}).ToShardingListAsync();
}

更多操作可以参考单元测试

Api

方法 Method SqlServer Unit Test MySql Unit Test
获取集合 ToShardingListAsync yes yes
第一条 ShardingFirstOrDefaultAsync yes yes
最大 ShardingMaxAsync yes yes
最小 ShardingMinAsync yes yes
是否存在 ShardingAnyAsync yes yes
分页 ToShardingPageResultAsync yes yes
数目 ShardingCountAsync yes yes
求和 ShardingSumAsync yes yes
分组 ShardingGroupByAsync yes yes

默认路由

抽象abstract 路由规则 tail 索引
AbstractSimpleShardingModKeyIntVirtualRoute 取模 0,1,2... =
AbstractSimpleShardingModKeyStringVirtualRoute 取模 0,1,2... =
AbstractSimpleShardingDayKeyDateTimeVirtualRoute 按时间 yyyyMMdd >,>=,<,<=,=,contains
AbstractSimpleShardingDayKeyLongVirtualRoute 按时间戳 yyyyMMdd >,>=,<,<=,=,contains
AbstractSimpleShardingWeekKeyDateTimeVirtualRoute 按时间 yyyyMMdd_dd >,>=,<,<=,=,contains
AbstractSimpleShardingWeekKeyLongVirtualRoute 按时间戳 yyyyMMdd_dd >,>=,<,<=,=,contains
AbstractSimpleShardingMonthKeyDateTimeVirtualRoute 按时间 yyyyMM >,>=,<,<=,=,contains
AbstractSimpleShardingMonthKeyLongVirtualRoute 按时间戳 yyyyMM >,>=,<,<=,=,contains
AbstractSimpleShardingYearKeyDateTimeVirtualRoute 按时间 yyyy >,>=,<,<=,=,contains
AbstractSimpleShardingYearKeyLongVirtualRoute 按时间戳 yyyy >,>=,<,<=,=,contains

注:contains表示为o=>ids.contains(o.shardingkey)

高级

批量操作

批量操作将对应的dbcontext和数据进行分离由用户自己选择第三方框架比如zzz进行批量操作或者batchextension

 virtualDbContext.BulkInsert<SysUserMod>(new List<SysUserMod>())
.BatchGroups.ForEach(pair =>
{
///zzz or other
pair.Key.BlukInsert(pair.Value);
});
var shardingBatchUpdateEntry = virtualDbContext.BulkUpdate<SysUserMod>(o => o.Id == "1", o => new SysUserMod()
{
Name = "name_01"
});
shardingBatchUpdateEntry.DbContexts.ForEach(context =>
{
//zzz or other
context.Where(shardingBatchUpdateEntry.Where).Update(shardingBatchUpdateEntry.UpdateExp);
});

手动路由

        var shardingQueryable = _virtualDbContext.Set<SysUserMod>().AsSharding();
//禁用自动路由
shardingQueryable.DisableAutoRouteParse();
//添加路由直接查询尾巴0的表
shardingQueryable.AddManualRoute<SysUserMod>("0");
//添加路由针对该条件的路由
shardingQueryable.AddManualRoute<SysUserMod>(o=>o.Id=="100");
var list=await shardingQueryable.ToListAsync();

自动建表

参考

事务

默认savechanges支持事务如果需要where.update需要手动开启事务


_virtualDbContext.BeginTransaction();
var shardingBatchUpdateEntry = _virtualDbContext.BulkUpdate<SysUserMod>(o=>o.Id=="123",o=>new SysUserMod()
{
Name = "name_modify"
});
foreach (var dbContext in shardingBatchUpdateEntry.DbContexts)
{
//zzz or other batch
}
await _virtualDbContext.SaveChangesAsync();

注意事项

该库的IVirtualDbContext.Set使用asnotracking所以基本不支持跟踪,目前框架采用AppDomain.CurrentDomain.GetAssemblies();

可能会导致程序集未被加载所以尽可能在api层加载所需要的dll

计划

  • [提供官网如果该项目比较成功的话]
  • [开发更完善的文档]
  • [支持分库]
  • [支持更多数据库查询]

最后

理论上该库的思想可以解决大部分orm的分表,目前是仅针对efcore的后期如果可以获取也会对其他orm进行sharding库的开发

该框架借鉴了大部分分表组件的思路,目前提供的接口都已经实现,并且支持跨表查询,基于分页查询该框架也使用了流式查询保证不会再skip大数据的时候内存会爆炸,至于groupby目前已经在开发支持了,相信不久后就会发布新版本,目前这个库只是一个刚刚成型的库还有很多不完善的地方希望大家多多包涵,如果喜欢的话也希望大家给个star.

该文档是我晚上赶工赶出来的也想趁热打铁希望更多的人关注,也希望更多的人可以交流。

凭借各大开源生态圈提供的优秀代码和思路才有的这个框架,希望可以为.Net生态提供一份微薄之力,该框架本人会一直长期维护,有大神技术支持可以联系下方方式欢迎star

博客

QQ群:771630778

个人QQ:326308290(欢迎技术支持提供您宝贵的意见)

个人邮箱:326308290@qq.com

基于efcore的分表组件开源的更多相关文章

  1. .NET 5 全自动分表组件,.NET 分表方案 ,分表架构与设计

    一.疑问&目的 1.1 分表使用场景 (1)可扩展架构设计,比如一个ERP用5年不卡,到了10就卡了因为数据太多了,这个时候很多人都是备份然后清空数据,这个工作大并且麻烦,以前的数据很难在使用 ...

  2. 架构组件:基于Shard-Jdbc分库分表,数据库扩容方案

    本文源码:GitHub·点这里 || GitEE·点这里 一.数据库扩容 1.业务场景 互联网项目中有很多"数据量大,业务复杂度高,需要分库分表"的业务场景. 这样分层的架构 (1 ...

  3. Spring-boot2X基于sharding-jdbc3.x分表分库

    ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC.Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的 ...

  4. 数据量大了一定要分表,分库分表组件Sharding-JDBC入门与项目实战

    最近项目中不少表的数据量越来越大,并且导致了一些数据库的性能问题.因此想借助一些分库分表的中间件,实现自动化分库分表实现.调研下来,发现Sharding-JDBC目前成熟度最高并且应用最广的Java分 ...

  5. TSharding:用于蘑菇街交易平台的分库分表组件

    tsharding TSharding is the simple sharding component used in mogujie trade platform. 分库分表业界方案 分库分表TS ...

  6. efcore分表下"完美"实现

    ShardingCore 如何呈现"完美"分表 这篇文章是我针对efcore的分表的简单介绍,如果您有以下需求那么可以自己选择是否使用本框架,本框架将一直持续更新下去,并且免费开源 ...

  7. efcore分表分库原理解析

    ShardingCore ShardingCore 易用.简单.高性能.普适性,是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2+的所有版本,支持efcore2+的所有数据 ...

  8. 基于SpringCloud实现Shard-Jdbc的分库分表模式,数据库扩容方案

    本文源码:GitHub·点这里 || GitEE·点这里 一.项目结构 1.工程结构 2.模块命名 shard-common-entity: 公共代码块 shard-open-inte: 开放接口管理 ...

  9. mysql、oracle分库分表方案之sharding-jdbc使用(非demo示例)

    选择开源核心组件的一个非常重要的考虑通常是社区活跃性,一旦项目团队无法进行自己后续维护和扩展的情况下更是如此. 至于为什么选择sharding-jdbc而不是Mycat,可以参考知乎讨论帖子https ...

随机推荐

  1. android中VideoView播放sd卡上面的视频

    (1)videoView组件只支持MP4和3gp格式的视屏播放,如果想播放其它视屏格式的文件,还得开发能够播放的视屏播放器 (2)videoView组件功能比较单一,如果想开发功能丰富的播放器,还得重 ...

  2. ssh问题之复盘

    一.问题发生.排查以及解决 某天H博士在登录B服务器时发现一个严重的问题,问题是H博士在执行脚本出现一个异常,这个异常是过去我执行脚本只需输入一次密码,现在要输入五六次,只有输入五六次后才能正确执行完 ...

  3. 写一个react hook:useLoading

    在写业务的过程中,我们总是会遇到这样的需求,在请求时显示一个 loading,然后请求结束后展示数据.以一个是不是 vip 的场景为例,如果不加入 loading 状态,页面可能在未请求的时候显示非 ...

  4. C#处理医学图像(二):基于Hessian矩阵的医学图像增强与窗宽窗位

    根据本系列教程文章上一篇说到,在完成C++和Opencv对Hessian矩阵滤波算法的实现和封装后, 再由C#调用C++ 的DLL,(参考:C#处理医学图像(一):基于Hessian矩阵的血管肺纹理骨 ...

  5. 【C++】《C++ Primer 》第四章

    第四章 表达式 一.基础 重载运算符:当运算符作用在类类型的运算对象时,用户可以自行定义其含义. 左值和右值: C中:左值可以在表达式左边,右值不能. C++中:当一个对象被用作右值的时候,用的是对象 ...

  6. linux常用命令--转载

    转载自: https://www.cnblogs.com/Qsunshine/p/10402179.html 常用指令 ls 显示文件或目录 -l列出文件详细信息l(list) -a列出当前目录下所有 ...

  7. 洛谷P1972 [SDOI2009]HH的项链(树状数组)

    题目链接: https://www.luogu.org/problemnew/show/P1972 题目描述: HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后 ...

  8. EnvironmentPostProcessor怎么做单元测试?阿里P7解答

    简介 从Spring Boot 1.3开始,我们可以在应用程序上下文刷新之前使用EnvironmentPostProcessor来自定义应用程序的Environment.Environment表示当前 ...

  9. Flask扩展点总结(信号)

    信号(源码) 信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作. pip3 install blinker 根据flask项目的请求流程来进行设置扩展点 1.中间件 from ...

  10. uni-app开发经验分享五: 解决三端页面兼容问题的方法

    在做uni-app开发的过程中,我们最头疼可能不是开发的过程中的逻辑,而是最后要做的三端兼容测试和修改,在我开发的项目中,这一步都是最头疼和令人头秃的过程,这里总结一些个人开发遇到的问题,希望对大家有 ...