一、SQL Server的主从复制搭建

1.1、SQL Server主从复制结构图

SQL Server的主从通过发布订阅来实现

1.2、基于SQL Server2016实现主从

新建一个主库“MyDB”



建一个表"SysUser"测试

CREATE TABLE [dbo].[SysUser](
[Id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[UserName] [varchar](50) NOT NULL,
[Account] [varchar](20) NOT NULL,
[Password] [varchar](100) NOT NULL,
[Phone] [varchar](50) NOT NULL,
[CreateTime] [datetime] NOT NULL,
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

搭建发布服务器

复制》配置分发

这里创建一个自己的路径,共享文件夹

分发数据库

发布服务器





然后下一步完成

启用代理

服务确认一下登陆权限

到这里发布服务器就建好了。

发布

发布就是把主库的数据或操作发布到发布服务器

现在主库里录入了两条数据

新建发布

选择发布的数据库

发布类型



这里有几种不同发布方式,根据自己业务场景选择,互联网一般是事务发布,有操作就同步。

选择同步的表

一直下一步到这里,勾选初始化订阅

代理安全性

下一步

发布名称

完成

这时候在上面设的发布服务器的共享文件夹中能看到有发布文件了

创建订阅

新建一个从库“MyDb_Copy”,为一个没创建表的空库

新建订阅

选择订阅的发布

选择推送方式(发布服务器主动推送),还是拉取方式(从库服务器拉取方式),一个从库选推送,多个从库选择拉取方式

选择订阅数据库

分发代理安全性

一直下一步,直到完成!

验证

看从库数据同步过来了

主库增加一条数据

从库看到也同步了

到这里SQL Server2016的主从复制就完成了!

二、MySQL的主从复制搭建

2.1、MySQL主从复制结构图

主库把增删查改的操作写入到binlog日志。

从库开启两个线程,一个IO线程,负责读取binlog日志到relay日志。一个SQL线程从relay日志读取数据写入从库DB

2.2、基于Docker搭建MySQL的主从

拉取镜像

docker pull mysql:5.7

准备两个文件,主库mysqld.cnf,上传到目录 /home/mysql/master

[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
#log-error = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
log-bin=mysql-bin
#id不要重复
server-id=11

从库mysald.cnf,上传到目录 /home/mysql/slave

[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
#log-error = /var/log/mysql/error.log
# By default we only accept connections from localhost
#bind-address = 127.0.0.1
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
#id不重复
server-id=22
#从库不需要事务,改MyISAM快些
default-storage-engine=MyISAM

创建主库容器

docker run --name mysql-master -p 3307:3306 -v /home/mysql/master:/etc/mysql/mysql.conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

创建从库容器

 docker run --name mysql-slave -p 3308:3306 -v /home/mysql/slave:/etc/mysql/mysql.conf.d -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

用连接工具连接上数据库,这里用DBeaver

配置主服务

首先,进入容器:

[root@localhost ~]# docker exec -it mysql-master /bin/bash
bash-4.2#

链接MySQL

bash-4.2# mysql -u root -p123456
mysql>

修改 root 可以通过任何客户端连接

mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
Query OK, 0 rows affected (0.00 sec) mysql>

重启Master服务器

mysql> exit
Bye
bash-4.2# exit
exit
[root@localhost ~]# docker restart mysql-master
mysql-master
[root@localhost ~]#

再次进入master容器

docker exec -it mysql-master /bin/bash

连接 MySQL

mysql -u root -p123456

查看数据库状态:


mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000005 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec) mysql>

把File的值“mysql-bin.000005”和 Position的值154记录下来

配置从服务器

首先,进入容器:

docker exec -it mysql-slave1 /bin/bash

连接 MySQL

mysql -u root -p123456

修改 root 可以通过任何客户端连接(默认root用户可以对从数据库进行编辑的)

ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

配置从同步主服务数据,执行如下SQL

change master to
master_host='192.168.101.20',
master_user='root',
master_log_file='mysql-bin.000005',
master_log_pos=154,
master_port=3307,
master_password='123456';
  • master_log_file='mysql-bin.000005' 上面主库记录下来的值
  • master_log_pos=154 上面主库记录下来的值

启动slave服务

mysql>start slave;

查看slave状态

show slave status \G;

验证主从库搭建结果

主库创建数据库

刷新从库,也把数据库同步过来了

主库创建一张表

CREATE TABLE MyDB.sys_user (
id int auto_increment NOT NULL,
user_name varchar(150) NOT NULL,
account varchar(20) NOT NULL,
password varchar(100) NOT NULL,
phone varchar(50) NOT NULL,
create_time DATETIME NOT NULL,
CONSTRAINT sys_user_PK PRIMARY KEY (id)
)
ENGINE=InnoDB
DEFAULT CHARSET=latin1
COLLATE=latin1_swedish_ci
AUTO_INCREMENT=1;

从库也同步了

主库插入数据,从库也能同步。

到这里,MySQL的主从搭建就完成了!

三、EF Core代码读写分离实现

这里用.NET6 +EF Core6.0 +SQLServer演示。

建一个.NET6的web程序

安装NuGet包

Microsoft.EntityFrameworkCore(6.0.7)
Microsoft.EntityFrameworkCore.SqlServer(6.0.7)

appsetting.json增加 ConnectinStrings节点

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"WriteConnection": "Data Source=.;Database=MyDB;User ID=sa;Password=123456",
"ReadConnection": "Data Source=.;Database=MyDB_Copy;User ID=sa;Password=123456"
}
}

增加一个类DBConnectionOption.cs来接收连接配置

  public class DBConnectionOption
{
public string WriteConnection { get; set; }
public string ReadConnection { get; set; }
}

增加一个类SysUser.cs来对应数据库表SysUser实体

    public class SysUser
{
public int Id { get; set; }
public string UserName { get; set; }
public string Account { get; set; }
public string Password { get; set; }
public string Phone { get; set; }
public DateTime CreateTime { get; set; }
}

增加一个类MyDBContext.cs来访问数库上下文

  public class MyDBContext : DbContext
{
private DBConnectionOption _readWriteOption;
public MyDBContext(IOptionsMonitor<DBConnectionOption> options)
{
_readWriteOption = options.CurrentValue;
} public DbContext ReadWrite()
{
//把链接字符串设为读写(主库)
this.Database.GetDbConnection().ConnectionString = this._readWriteOption.WriteConnection;
return this;
}
public DbContext Read()
{
//把链接字符串设为之读(从库)
this.Database.GetDbConnection().ConnectionString = this._readWriteOption.ReadConnection;
return this;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(this._readWriteOption.WriteConnection); //默认主库
}
public DbSet<SysUser> SysUser { get; set; }
}

增加一个类DbContextExtend.cs来扩展上下文修改连接字符串

  /// <summary>
/// 拓展方法
/// </summary>
public static class DbContextExtend
{
/// <summary>
/// 只读
/// </summary>
/// <param name="dbContext"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static DbContext Read(this DbContext dbContext)
{
if (dbContext is MyDBContext)
{
return ((MyDBContext)dbContext).Read();
}
else
throw new Exception();
}
/// <summary>
/// 读写
/// </summary>
/// <param name="dbContext"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static DbContext ReadWrite(this DbContext dbContext)
{
if (dbContext is MyDBContext)
{
return ((MyDBContext)dbContext).ReadWrite();
}
else
throw new Exception();
}
}

修改Program.cs,增加

builder.Services.Configure<DBConnectionOption>(builder.Configuration.GetSection("ConnectionStrings"));//注入多个链接
builder.Services.AddTransient<DbContext, MyDBContext>();

验证

在HomeController的Index方法里实现读写分离操作

        public IActionResult Index()
{ //新增-------------------
SysUser user = new SysUser()
{
UserName="李二狗",
Account="liergou",
Password=Guid.NewGuid().ToString(),
Phone="13345435554",
CreateTime=DateTime.Now
}; Console.WriteLine($"新增,当前链接字符串为:{_dbContext.Database.GetDbConnection().ConnectionString}");
_dbContext.ReadWrite().Add(user);
_dbContext.SaveChanges(); //只读--------------------------------
var dbContext = _dbContext.Read();
var users= _dbContext.Read().Set<SysUser>().ToList();
Console.WriteLine($"读取SysUser,数量为:{users.Count},当前链接字符串为:{_dbContext.Database.GetDbConnection().ConnectionString}"); return View();
}

执行结果:

查看数据库,新增的数据也查入成功了。

这里读程序读写分离也完成了!

有没有细心的朋友发现读的时候日志只显示读到了3条记录,而上面一共有4条记录。

原因是主从同步会有延迟,从库没那么快同步到数据,一般都有个0.几到1秒的延迟,这个可以调优,这里就不说多内容了,有兴趣的可以去查资料操作一下。

到这里全部就完成了!

源码地址:https://github.com/weixiaolong325/EFCoreReadWriteSeparate

SQL Server、MySQL主从搭建,EF Core读写分离代码实现的更多相关文章

  1. Mysql主从配置,实现读写分离

    大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够.到了数据业务层.数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连接操作,数据库必然会崩溃,数据丢 ...

  2. 黄聪:Mysql主从配置,实现读写分离

    大型网站为了软解大量的并发访问,除了在网站实现分布式负载均衡,远远不够.到了数据业务层.数据访问层,如果还是传统的数据结构,或者只是单单靠一台服务器扛,如此多的数据库连接操作,数据库必然会崩溃,数据丢 ...

  3. 基于mysql主从同步的proxy读写分离

    mysql-proxy 简介 MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测.分析或改变它们的通信.它使用灵活,没有限制,常见的用途包括:负载 ...

  4. docker配置mysql主从与django实现读写分离

    一.搭建主从mysql环境 1 下载mysql镜像 docker pull mysql:5.7 2 运行刚下载的mysql镜像文件 # 运行该命令之前可以使用`docker images`是否下载成功 ...

  5. SQL Server 复制:事务发布(读写分离)

    一.背景 在复制的运用场景中,事务发布是使用最为广泛的,我遇到这样一个场景:在YangJiaLeClub数据库中有表.存储过程.视图.用户定义函数,需要提供给其它程序读取放入缓存,程序需要比较及时的获 ...

  6. mysql主从之基于atlas读写分离

    一 mysql读写分离的概念 写在主库,主库一般只有一个,读可以分配在多个从库上,如果写压力不大的话,也能把读分配到主库上. 实现是基于atlas实现的,atlas是数据库的中间件,程序只需要连接at ...

  7. mysql+spring+mybatis实现数据库读写分离[代码配置] .

    场景:一个读数据源一个读写数据源. 原理:借助spring的[org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource] ...

  8. 【爬坑笔记】c# 如何通过EF Core读写sql server的类似double型字段

    =============================================== 2019/8/31_第1次修改                       ccb_warlock == ...

  9. ### MySQL主从搭建Position

    一.MySQL主从搭建 搭建主从架构的MySQL常用的有两种实现方式: 基于binlog的fileName + postion模式完成主从同步. 基于gtid完成主从同步搭建. 本篇就介绍如何使用第一 ...

随机推荐

  1. 新作!分布式系统韧性架构压舱石OpenChaos

    摘要:本文首先以现今分布式系统的复杂性和稳定性的需求引出混沌工程概念,并阐述了OpenChaos在传统混沌工程上的优化与创新. 背景 随着Serverless,微服务(含服务网格)与越来越多的容器化架 ...

  2. 图解KMP字符串匹配算法+代码实现

    kmp算法跟之前讲的bm算法思想有一定的相似性.之前提到过,bm算法中有个好后缀的概念,而在kmp中有个好前缀的概念,什么是好前缀,我们先来看下面这个例子. 观察上面这个例子,已经匹配的abcde称为 ...

  3. Sharding JDBC案例实战

    基础分库 以下实例基于shardingsphere 4.1.0 + SpringBoot 2.2.5.RELEASE版本 依赖导入: <properties> <project.bu ...

  4. 每日一题20180330-Linux

    一.问题 1.1 统计/var/log/下所有文件个数 1.2 查找出/var/log目录下面修改时间是7天以前,大小在50k到2M之间,并以.log结尾的文件把这些文件复制到/data目录中 1.3 ...

  5. cut-列过滤

    列过滤命令. 语法 cut [选项] 要过滤的字符串 选项 -f 以字段为单位进行分割 -c 以字符为单位进行分割 -b 以字节为单位进行分割 -d 以分割符为单位进行分割,分隔符可以是"冒 ...

  6. linux系统下文件误删除该如何恢复?

    一.linux误删除数据的场景 在实际的工作中,朋友们可能会将linux服务器上的文件不小心误删除掉了.而且越是资历老的工程师越容易犯这样的错误,敲代码的速度也是够快,啪啪rm -rf一个回车,然后就 ...

  7. 自动装箱与自动拆箱——JavaSE基础

    自动装箱与自动拆箱 自动装箱与拆箱就是编译器蜜糖(Compiler Sugar) Integer a = 234; // 自动装箱,实际上是Integer a = Integer.valueOF(23 ...

  8. Kafka 负载均衡在 vivo 的落地实践

    ​vivo 互联网服务器团队-You Shuo 副本迁移是Kafka最高频的操作,对于一个拥有几十万个副本的集群,通过人工去完成副本迁移是一件很困难的事情.Cruise Control作为Kafka的 ...

  9. NOI Online 2022 一游

    NOI Online 2022 一游 TG 啊,上午比提高,根据去年的经验,题目配置估计那至少一黑 所以直接做 1 题即可.(确信) 总体:估分 140,炸了但没完全炸 奇怪的过程 开题:3 2 1 ...

  10. Base64编码知识详解

    在我们进行前端开发时,针对项目优化,常会提到一条:针对较小图片,合理使用Base64字符串替换内嵌,可以减少页面http请求. 并且还会特别强调下,必须是小图片,大小不要超过多少KB,等等. 那么,B ...