如今,我们操作数据库一般用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. Foreground-aware Image Inpainting

    引言 语义分割得到边缘信息指导修复其三 存在问题:现在的图像修复方法主要的通过周围像素来修复,当修复区域与前景区域(显著物体)有交叠时,由于修复区域缺失前景与背景的时间内容导致修复结果不理想. 提出方 ...

  2. wsgi_uwsgi_nginx

    1.一些重要概念 https://www.cnblogs.com/xiaonq/p/8932266.html 1.1 web容器 什么是web容器 1.web容器是帮助我们部署java.php.pyt ...

  3. Beta冲刺——用户测试报告

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta 冲刺 这个作业的目标 团队进行Alpha冲刺 作业正文 正文 其他参考文献 无 用户测试报告 用户 ...

  4. unity官网安装教程

    于今天起记录与回忆游戏开发相关一些小目标 2020-12-01 第一篇正式的博客就从软件的安装开始吧 unity个人版是免费的不用刻意去找破解版什么的 unity官网安装 1.unity.cn uni ...

  5. 使用 IDEA 创建多模块项目

    网上找如何创建多模块项目的资料,大多类似,实践中又各有问题,此文为摸索之后总结 最终项目结构如下: 项目引用关系:app → service → dao 新建父项目 multi-parent mult ...

  6. 在django中使用原生sql语句

    raw # row方法:(掺杂着原生sql和orm来执行的操作) res = CookBook.objects.raw('select id as nid from epos_cookbook whe ...

  7. node-sass版本问题

    node-sass sass-loader的问题 出现了版本的问题 版本太高 版本不兼容解决方法: cnpm i node-sass@4.14.1 cnpm i sass-loader@7.3.1 - ...

  8. 第十一章 Python 支撑正则表达式处理的re模块

    re模块是Python中支持正则表达式处理的模块,老猿学了之后,发现这部分内容太多,要表述清楚需要开单章才能写清楚,但老猿觉得re模块的使用对多数人来说要通过教程学习去熟练掌握很难,需要经常接触练习加 ...

  9. 使用文件描述符作为Python内置函数open的file实参调用示例

    一.关于文件描述符 open()函数的file参数,除了可以接受字符串路径外,还可以接受文件描述符(file descriptor),文件描述符是个整数,对应程序中已经打开的文件. 文件描述符是操作系 ...

  10. PyQt(Python+Qt)学习随笔:Qt Designer中部件的mouseTracking和tabletTracking属性

    在Qt Designer中的部件属性设置中,有mouseTracking和tabletTracking两个属性,这两个属性是跟踪鼠标或平板触控笔的移动轨迹的. 一.mouseTracking mous ...