EFCore.Sharding(EFCore开源分表框架)
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.MySql | MySql支持 |
EFCore.Sharding.PostgreSql | PostgreSql支持 |
EFCore.Sharding.SQLite | SQLite支持 |
EFCore.Sharding.SqlServer | SqlServer支持 |
EFCore.Sharding.Oracle | Oracle支持(暂不支持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
using(IShardingRepository _db = DbFactory.GetShardingRepository())
{
}
然后即可进行数据操作:
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,而且封装了常用数据库操作,使用比较简单
详细使用方式参考 链接
常用配置
多主键支持
在实体类上加上EFCore.Sharding.DataAnnotations.Keys特性即可
自动建表时会自动创建主键
/// <summary>
/// 单元测试表
/// </summary>
[Table("Base_UnitTest")]
[Index(false, nameof(CreateTime))]
[Index(false, nameof(Age))]
[Keys(nameof(Id), nameof(UserName))]
public class Base_UnitTest
{
/// <summary>
/// 代理主键
/// </summary>
[Key, StringLength(50)]
public String Id { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 用户名
/// </summary>
public String UserName { get; set; }
/// <summary>
/// Age
/// </summary>
public Int32? Age { get; set; }
}
索引支持
在实体类上加上EFCore.Sharding.DataAnnotations.Index特性即可
可以设置多个Index特性
自动建表时会自动创建索引
/// <summary>
/// 单元测试表
/// </summary>
[Table("Base_UnitTest")]
[Index(false, nameof(CreateTime))]
[Index(false, nameof(Age))]
[Keys(nameof(Id), nameof(UserName))]
public class Base_UnitTest
{
/// <summary>
/// 代理主键
/// </summary>
[Key, StringLength(50)]
public String Id { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
/// <summary>
/// 用户名
/// </summary>
public String UserName { get; set; }
/// <summary>
/// Age
/// </summary>
public Int32? Age { get; set; }
}
总结
这个简单实用强大的框架希望能够帮助到大家,力求为.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开源分表框架)的更多相关文章
- efcore使用ShardingCore实现分表分库下的多租户
efcore使用ShardingCore实现分表分库下的多租户 介绍 本期主角:ShardingCore 一款ef-core下高性能.轻量级针对分表分库读写分离的解决方案,具有零依赖.零学习成本.零业 ...
- 分布式事务-Sharding 数据库分库分表
Sharding (转)大型互联网站解决海量数据的常见策略 - - ITeye技术网站 阿里巴巴Cobar架构设计与实践 - 机械机电 - 道客巴巴 阿里分布式数据库服务原理与实践:沈询_文档下载 ...
- 基于代理的数据库分库分表框架 Mycat实践
192.168.199.75 MySQL . MyCAT master 192.168.199.74 MySQL slave 192.168.199.76 MySQL standby master 如 ...
- 分库分表框架ShardingSphere入门学习1
背景 传统的将数据集中存储至单一数据节点的解决方案,在性能.可用性和运维成本这三方面已经难于满足互联网的海量数据场景. 从性能方面来说,由于关系型数据库大多采用 B+ 树类型的索引,在数据量超过阈值的 ...
- efcore分表分库原理解析
ShardingCore ShardingCore 易用.简单.高性能.普适性,是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2+的所有版本,支持efcore2+的所有数据 ...
- .Net下极限生产力之efcore分表分库全自动化迁移CodeFirst
.Net下极限生产力之分表分库全自动化Migrations Code-First ## 介绍 本文ShardinfCore版本x.6.x.x+ 本期主角: - [`ShardingCore`](htt ...
- 分库分表利器之Sharding Sphere(深度好文,看过的人都说好)
Sharding-Sphere Sharding-JDBC 最早是当当网内部使用的一款分库分表框架,到2017年的时候才开始对外开源,这几年在大量社区贡献者的不断迭代下,功能也逐渐完善,现已更名为 S ...
- Sharding JDBC整合SpringBoot 2.x 和 MyBatis Plus 进行分库分表
Sharding JDBC整合SpringBoot 2.x 和 MyBatis Plus 进行分库分表 交易所流水表的单表数据量已经过亿,选用Sharding-JDBC进行分库分表.MyBatis-P ...
- Furion分表分库我也要happy coding
Furion分表分库集成ShardingCore ShardingCore ShardingCore 易用.简单.高性能.普适性,是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efco ...
随机推荐
- jQuery的简单用法(jQuery的简介,选择器,属性和css,文档处理)
一.jQuery简介 1.1. JS库 JavaScript 库封装了很多预定义的对象和实用函数.能帮助使用者建立有高难度交互客户端页面, 并且兼容各大浏览器. 1.2. 当前流行的 JavaSc ...
- 基于arduino、百度云、采用django、redis鱼缸在线监控
大家好,今天我给大家分享一下之前做的一个鱼缸远程监控的案例,希望有人喜欢 首先给大家看一下结构框架,由于我之前买的arduino开发板不带wifi功能,所有是通过pc机转发一下上的百度云,最近我刚购买 ...
- TensorFlow 卷积神经网络手写数字识别数据集介绍
欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! 手写数字识别 接下来将会以 MNIST 数据集为例,使用卷积层和池 ...
- ElasticSearch 9200 9300 端口
9300端口: ES节点之间通讯使用 9200端口: ES节点 和 外部 通讯使用 9300是TCP协议端口号,ES集群之间通讯端口号 9200端口号,暴露ES RESTful接口端口号
- linux 中的页缓存和文件 IO
本文所述是针对 linux 引入了虚拟内存管理机制以后所涉及的知识点.linux 中页缓存的本质就是对于磁盘中的部分数据在内存中保留一定的副本,使得应用程序能够快速的读取到磁盘中相应的数据,并实现不同 ...
- Python终端打印彩色文字
终端彩色文字 class Color_f: black = 30 red = 31 green = 32 yellow= 33 blue = 34 fuchsia=35 cyan = 36 white ...
- 【Springboot】实例讲解Springboot整合OpenTracing分布式链路追踪系统(Jaeger和Zipkin)
1 分布式追踪系统 随着大量公司把单体应用重构为微服务,对于运维人员的责任就更加重大了.架构更复杂.应用更多,要从中快速诊断出问题.找到性能瓶颈,并不是一件容易的事.因此,也随着诞生了一系列面向Dev ...
- thinkphp5.1中使用链式操作的坑
1.在进行tp5->tp5.1的时候,没有想太多,直接使用之前的代码:结果在该操作中,多次调用该get方法,tp5.1的链式操作一直保持了之前的搜索条件,截图如下:(具体的代码没有展示) 2.然 ...
- 【swagger】C# 中 swagger 的使用及避坑
@ 目录 1 安装 2 修改名称和版本号 3 显示说明 4 显示控制器注释及汉化 5 路由相同,查询参数不同的方法 6 忽略 Model 中的某些字段 7 传递 header 8 出错时的 HTTP ...
- bootstrip安装
什么是Bootstrap Bootstrap,来自 Twitter,是目前最受欢迎的前端框架.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的,它简洁灵活,使得 Web 开发更加 ...