查看原文
其他

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

DotNet 2021-09-23

(给DotNet加星标,提升.Net技能

转自:寒空飞箭
cnblogs.com/coldairarrow/p/12733886.html

简介


本框架旨在为EF Core提供Sharding(即读写分离分库分表)支持,不仅提供了一套强大的普通数据操作接口,并且降低了分表难度,支持按时间自动分表扩容,提供的操作接口简洁统一.


源码地址:https://github.com/Coldairarrow/EFCore.Sharding




配置


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());
});



使用


配置完成,下面开始使用,使用方式非常简单,与平常使用基本一致

首先获取分片仓储接口IShardingRepository


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


然后即可进行数据操作:






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();
}
}
}




全程无需人工干预,系统会自动定时创建分表,十分简单好用


性能测试


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,而且封装了常用数据库操作,使用比较简单


详细使用方式参考https://github.com/Coldairarrow/EFCore.Sharding/blob/master/examples/Demo.DI/Program.cs


总结


这个简单实用强大的框架希望能够帮助到大家,力求为.NET生态贡献一份力,大家一起壮大.NET生态。


Github地址:https://github.com/Coldairarrow


推荐阅读  点击标题可跳转
一起读源码C#并发队列内部世界 .NET Core篇.NET Core 3.0 WPF MVVM框架Prism系列之导航系统Nginx知多少系列之介绍


看完本文有收获?请转发分享给更多人

关注「DotNet」加星标,提升.Net技能 

好文章,我在看❤️

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存