如今,我们操作数据库一般用ORM框架

现在用.NET Core + EFCore + SqlServer 实现数据读写分离

介绍

为什么要读写分离?

降低数据库服务器的压力

如何实现读写分离?

1.一个主库多个从库

2.配置主库复制数据到从库

为什么一个主库多个从库?

一般查询多于增删改,这就是我们常说的二八原则,20%操作是增删改,80%操作是查询

是否有缺点?

有延迟

如何解决延迟问题?

比较及时性的数据还是通过主库查询

具体如何实现?

通过发布服务器,主库发布,而从库订阅,从而实现主从库

实现

SqlServer 实现

1.使用SqlServer 2019,新建一个主库,创建表,再通过本地发布创建发布,

然后通过本地订阅订阅主库,创建两个从库

2.配置AlwaysOn高可用性

https://www.cnblogs.com/chenmh/p/4484176.html

.NET Core MVC项目实现

项目结构

首先,在appsettings.json配置数据库连接字符串

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"EFCoreTestToRead": "Server=GREAMBWANG-DC\\MSSQLSERVER2019;Database=EFCoreTestToRead01;Trusted_Connection=True;,Server=GREAMBWANG-DC\\MSSQLSERVER2019;Database=EFCoreTestToRead02;Trusted_Connection=True;",
"EFCoreTestToWrite": "Server=GREAMBWANG-DC\\MSSQLSERVER2019;Database=EFCoreTest;Trusted_Connection=True;"
}
}

Models层实现

创建模型

public class UserInfo
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; } }

创建上下文

public class EFCoreContext : DbContext
{
public EFCoreContext(string connectionString)
{
ConnectionString = connectionString; //创建数据库
//Database.EnsureCreated();
} private string ConnectionString { get; } public DbSet<UserInfo> UserInfo { get; set; } /// <summary>
/// 配置连接数据库
/// </summary>
/// <param name="optionsBuilder"></param>
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer(ConnectionString); } protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder); //初始化数据
modelBuilder.Entity<UserInfo>().HasData(new List<UserInfo>()
{
new UserInfo() { Id = 1, Name = "哈哈", Age = 17 },
new UserInfo() { Id = 2, Name = "呵呵", Age = 18 },
new UserInfo() { Id = 3, Name = "嘻嘻", Age = 19 }
});
}
}

创建上下文工厂

读写枚举

public enum WriteAndReadEnum
{
Write,
Read
}

接口

public interface IDbContextFactory
{
EFCoreContext CreateContext(WriteAndReadEnum writeAndRead);
}

实现

在实现数据查询上,可以使用不同的策略,一般有随机策略,权重策略,轮询策略

随机策略:随机选择一个从库进行查询

权重策略:根据权重比例选择从库查询

轮询策略:根据顺序选择从库查询

Models层完成

public class DbContextFactory : IDbContextFactory
{
private IConfiguration Configuration { get; }
private string[] ReadConnectionStrings;
public DbContextFactory(IConfiguration configuration)
{
Configuration = configuration;
ReadConnectionStrings = Configuration.GetConnectionString("EFCoreTestToRead").Split(",");
} public EFCoreContext CreateContext(WriteAndReadEnum writeAndRead)
{
string connectionString = string.Empty;
switch (writeAndRead)
{
case WriteAndReadEnum.Write:
connectionString = Configuration.GetConnectionString("EFCoreTestToWrite");
break;
case WriteAndReadEnum.Read:
connectionString = GetReadConnectionString();
break;
default:
break;
}
return new EFCoreContext(connectionString);
} private string GetReadConnectionString()
{
/*
* 随机策略
* 权重策略
* 轮询策略
*/ //随机策略
string connectionString = ReadConnectionStrings[new Random().Next(0, ReadConnectionStrings.Length)]; return connectionString;
}
}

在Web层中

在Startup的ConfigureServices方法添加依赖注入

services.AddScoped<IDbContextFactory, DbContextFactory>();

操作

 

public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger; public IDbContextFactory DbContextFactory { get; } public HomeController(ILogger<HomeController> logger,IDbContextFactory dbContextFactory)
{
_logger = logger;
DbContextFactory = dbContextFactory;
} public IActionResult Index()
{
//写入操作
EFCoreContext writeContext = DbContextFactory.CreateContext(WriteAndReadEnum.Write);
writeContext.UserInfo.Add(new UserInfo() { Name = "AA", Age = 20 });
writeContext.SaveChanges(); //查询操作
EFCoreContext readContext = DbContextFactory.CreateContext(WriteAndReadEnum.Read);
UserInfo userInfo = readContext.UserInfo.OrderByDescending(u => u.Id).FirstOrDefault(); return View();
}
}

总结

sqlserver读写分离后,读库和主库会有一定时间的延迟,当业务逻辑是增加记录后马上刷新列表之类的逻辑时

alwayson ?
其实这个延迟一般情况下不会太大, 一般几十ms 到 几百 ms. 也可以在增加记录之后 Thread.Sleep(1000) 休眠一秒, 然后再刷新列表, 问题不大的。
特别重要的(关系到钱)的业务, 就只能直接读主库了。

要是不容许有不一致性,那你就别分离了。

但是也可以  业务逻辑是增加记录后马上刷新列表之类的逻辑时-->新增成功之后将数据添加到本地集合(BindingList/ObservableCollection)这样能将结果通知到UI列表显示,而不是再从新读取全部数据。

实际上读写分离相当程度上是增加了问题、增加了困难,而不是减少了问题。真正应该首先做到的是,尽量在逻辑中避免使用事务概念、甚至避免使用关系数据库,尽量将面向数据库增删改查的程序改为面向(几百万)微服务的并发程序。然而很多人没有这方面的理解,认为把数据库分库分表读写分离这类“优化”最简单,所以一味地浪费精力在看似最简单实则已经逐步脱离时代的优化概念上。

分离数据库不是什么好主意,甚至可以说是“坑爹”的。现在的大规模高性能的程序,实际上是去掉增删改查数据库层概念,而是面向全局一致性分布式数据缓存层来编程。

高性能系统是去低级的数据库层,而是使用中间件层,也就是在后台业务逻辑处理中也要至少三层设计。

具备维护功能的代码本身应该是读写在写的数据库上,而不是写在写数据库,而读在读数据库

.NET+SqlServer 实现数据读写分离的更多相关文章

  1. Python3 实现数据读写分离设计

    前言 首先读写分离可以保证数据库的稳定,简单的说就是当网站访问量大时,读写都在一个库,很有可能会出现脏数据的情况,如果采取阻塞似操作,那么用户体验就会变得更差. 而且目前大多数网站的读写是失衡的,以淘 ...

  2. 查看SQL Server数据读写分离,并设置读写分离

    1. 查看读写分离脚本,直接执行以下脚本: select name,is_read_committed_snapshot_on from sys.databases 执行结果列表中,name表示数据库 ...

  3. sqlserver实现数据库读写分离介绍

    对于负载均衡,笔者经常接触的当属Oracle的负载均衡机制.下面我们重点介绍Sql Server 2005是如何实现负载均衡的,感兴趣的朋友可以参考下哈 Internet的规模每一百天就会增长一倍,客 ...

  4. Mycat实现Mysql数据库读写分离

    Linux和Windows环境下搭建Mycat数据读写分离 前提需要:1.服务器装有JVM虚拟机,就是JDK.2.两个Mysql数据库已经实现主从复制,参考:https://www.cnblogs.c ...

  5. Amoeba读写分离(MySQL)

    实验操作环境: centos服务器  三台机器 role: 192.168.189.129  master-主 192.168.189.130  master-从 192.168.189.131    ...

  6. LAMP企业架构读写分离

    1.1  LAMP企业架构读写分离 LAMP+Discuz+Redis缓解了MYSQL的部分压力,但是如果访问量非常大,Redis缓存中第一次没有缓存数据,会导致MYSQL数据库压力增大,此时可以基于 ...

  7. 三十五.MySQL读写分离 MySQL多实例 、MySQL性能调优

    1.实现MySQL读写分离 搭建一主一从结构 配置maxscale代理服务器 测试分离配置   1.1 搭建一主一从结构 192.168.4.51 主 192.168.4.52 从 测试OK   1. ...

  8. 使用Adivisor配置增强处理,来实现数据库读写分离

    一.先写一个demo来概述Adivisor的简单使用步骤 实现步骤: 1.通过MethodBeforeAdivice接口实现前置增强处理 public class ServiceBeforeAdvis ...

  9. 阿里P8架构师谈:数据库分库分表、读写分离的原理实现,使用场景

    本文转载自:阿里P8架构师谈:数据库分库分表.读写分离的原理实现,使用场景 为什么要分库分表和读写分离? 类似淘宝网这样的网站,海量数据的存储和访问成为了系统设计的瓶颈问题,日益增长的业务数据,无疑对 ...

随机推荐

  1. Java基础教程——Lambda表达式

    Lambda表达式 Java8引入Lambda表达式,可以使代码更简洁. 格式:参数,箭头,代码 (参数名)->{代码} Lambda表达式体现了"函数式编程思想"-- 面向 ...

  2. 3.深入Istio:Pilot配置规则ConfigController

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的Istio源码是 release 1.5. Config Controller ...

  3. SpringBoot整合阿里短信服务

    导读 由于最近手头上需要做个Message Gateway,涉及到:邮件(点我直达).短信.公众号(点我直达)等推送功能,网上学习下,整理下来以备以后使用. 步骤 点我直达 登录短信服务控制台 点我直 ...

  4. sqli-labs-master less05 及 Burp Suite暴力破解示例

    一.首先测试显示内容 例:http://localhost/sqli-labs-master/Less-5/?id=1 http://localhost/sqli-labs-master/Less-5 ...

  5. .Net Core AddTransient、AddScoped和AddSingleton的使用

    区别: AddTransient 每次service请求都是获得不同的实例,暂时性模式:暂时性对象始终不同,无论是不是同一个请求(同一个请求里的不同服务)同一个客户端,每次都是创建新的实例 AddSc ...

  6. BootstrapBlazor 组件库介绍

    项目介绍 演示系统地址:https://www.blazor.zone Blazor 是一个使用 .NET 生成交互式客户端 Web UI 的框架: 使用 C# 代替 JavaScript 来创建丰富 ...

  7. 单体->集群->模块化->分布式微服务

    开头语: 每篇一段开头语,在技术的道路中寻找文采的乐趣.(如果随笔中都是大白话勿喷,兄弟姐妹们) 单体项目 单体项目适用于小型开发,或自己来进行小项目的测试和使用. 单体项目的缺憾 多人开发项目所出现 ...

  8. 喝完可乐桶后程序员回归本源,开源Spring基础内容

    周六了,又是摸鱼的一天,今天还有点不在状态,脑瓜子迷迷糊糊的,昨晚出去喝可乐桶喝的脑子到现在都不是很正常(奉劝各位可以自己小酌:450ml威士忌+1L多一点可乐刚刚好,可能是我酒量不好),正好没啥事就 ...

  9. Centos7 之间的文件拷贝

    环境: 内网了两台cenots7主机 scp命令 scp [参数] [原路径] [目标路径] scp -P 22022 /home/file.war root@192.168.253.172:/hom ...

  10. ripple Failed to load resource: the server responded with a status of 404 (Not Found)

    在VS2015中使用Cordova + typescript开发中,遇到个问题. 在javascript console 中提示: Failed to load resource: the serve ...