windows NLB实现MSSQL读写分离--从数据库集群读负载均衡

主从模式,几乎大部分出名的数据库都支持的一种集群模式。

当Web站点的访问量上去之后,很多站点,选择读写分离,减轻主数据库的的压力。当然,一主多从也可以作用多个功能,比如备份。这里主要演示如何实现从数据库集群的读负载均衡

搭建一主三从的MSSQL集群

192.168.99.250  //主服务器

192.168.99.8  //从服务器(WIN-6S3JNU8C4TB)
192.168.99.10  //从服务器(WIN-HF1GQ5U288H)
192.168.99.11  //从服务器(WIN-EAPJ2QB5AGM)

本地发布

一般而言,我们只需要安装数据库引擎服务即可。复制服务需要另外安装,所以我们进行发布/订阅模式的话,需要安装复制组件

192.168.99.250 主服务器发布数据同步,接三台从服务器订阅发布。

本地订阅

同样本地订阅,也需要安装复制组件。

模拟写数据

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using System.Text;
using System.Linq;

namespace Write
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始写入模拟数据");
            var ef = new EFDbContext();
            var rand = new Random();
            StringBuilder str1 = new StringBuilder();
            str1.Append("赵、钱、孙、李、周、吴、郑、王、冯、陈、楮、卫、蒋、沈、韩、杨、朱、秦、尤、许、何、吕、施、张、孔、曹");
            var familyNameItems = str1.ToString().Split("、");

            StringBuilder str2 = new StringBuilder();
            str2.Append("宏子 婷婷 蓉蓉 丽娜 娜 钰 天霞 官君 红梅 淑慧 海娟 洪山 ");
            str2.Append("盼丽 艳红 甜甜 璨 彬彬 银红 晨曦 婷 广荣 蓓 小艳 欣如 辅仁 嘉 雯婷 玉红 晨霞 ");
            str2.Append("涵 明 丽娜 青 茵 瑞微 逸群 思阳 臻 勇 志光 克涛 靖华 慧霞 卫伟 藜文 清华 莎 晓新 ");
            str2.Append("安安 荌荌 安卉 安娜 安妮 安然 傲冬 傲晴 傲雪 白雪 白云 碧螺 碧菡 碧玉 冰蓝 ");
            str2.Append("含烟 含玉 涵菡 晗蕾 涵韵 晗玥 寒凝 寒香 寒雁 和悌 和美 和怡 和雅 和璧 和玉 ");
            str2.Append("红螺 虹雨 虹彩 虹英 虹颖 虹影 怀玉 慧心 慧颖 慧雅 慕青 问兰 尔岚 元香 曼文");
            var firstNameItems = str2.ToString().Split(" ");

            while (true)
            {
                string userName = "15" + rand.Next(100000000, 999999999).ToString();
                ef.OAUser.Add(new OAUser
                {
                    UserName = userName,
                    PassWord = "123456",
                    Salt = rand.Next(1111111, 6666666).ToString(),
                    NickName = familyNameItems[rand.Next(0, familyNameItems.Count())]
                    + firstNameItems[rand.Next(0, firstNameItems.Count())],
                    IsFrozen = false,
                    CreateTime = DateTime.Now
                });
                ef.SaveChanges();
                Console.WriteLine($"成功将用户{userName}资料写入");
            }
        }
    }

    public class EFDbContext : DbContext
    {
        public EFDbContext()
        {
            base.ChangeTracker.AutoDetectChangesEnabled = false;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=192.168.99.250;Initial Catalog=Test;User Id=sa;Password=123;",
                n => n.UseRowNumberForPaging());
        }

        /// <summary>
        /// 用户表
        /// </summary>
        public DbSet<OAUser> OAUser { set; get; }
    }

    /// <summary>
    /// 用户表
    /// </summary>
    [Table("OAUser")]
    public class OAUser
    {
        /// <summary>
        /// 主健
        /// </summary>
        [Key]
        public int Id { set; get; }

        /// <summary>
        /// 用户账号
        /// </summary>
        [Required, MaxLength(15), MinLength(6)]
        public string UserName { set; get; }

        /// <summary>
        /// 用户密码
        /// </summary>
        [Required, StringLength(64)]
        public string PassWord { set; get; }

        /// <summary>
        /// 昵称
        /// </summary>
        [Required, StringLength(30)]
        public string NickName { get; set; }

        /// <summary>
        /// 加密盐
        /// </summary>
        [Required, StringLength(20)]
        public string Salt { set; get; }

        /// <summary>
        /// 是否冻结
        /// </summary>
        public bool IsFrozen { set; get; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { set; get; }
    }
}

搭建NLB集群

192.168.99.120 //公共IP

192.168.99.8
192.168.99.10
192.168.99.11

模拟读取数据库

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using System.Text;
using System.Linq;

namespace Read
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("模拟大量读取");
            var ef = new EFDbContext();
            var i = 0;
            while (i < 1000)
            {
                i++;
                var user = ef.OAUser.OrderBy(n => Guid.NewGuid()).Take(1).FirstOrDefault();
                Console.WriteLine($"读取用户{user.UserName}资料");
            }
            Console.WriteLine("读取完毕");
        }
    }

    public class EFDbContext : DbContext
    {
        public EFDbContext()
        {
            base.ChangeTracker.AutoDetectChangesEnabled = false;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=192.168.99.120;Initial Catalog=oa;User Id=sa;Password=123;",
                n => n.UseRowNumberForPaging());
        }

        /// <summary>
        /// 用户表
        /// </summary>
        public DbSet<OAUser> OAUser { set; get; }
    }

    /// <summary>
    /// 用户表
    /// </summary>
    [Table("OAUser")]
    public class OAUser
    {
        /// <summary>
        /// 主健
        /// </summary>
        [Key]
        public int Id { set; get; }

        /// <summary>
        /// 用户账号
        /// </summary>
        [Required, MaxLength(15), MinLength(6)]
        public string UserName { set; get; }

        /// <summary>
        /// 用户密码
        /// </summary>
        [Required, StringLength(64)]
        public string PassWord { set; get; }

        /// <summary>
        /// 昵称
        /// </summary>
        [Required, StringLength(30)]
        public string NickName { get; set; }

        /// <summary>
        /// 加密盐
        /// </summary>
        [Required, StringLength(20)]
        public string Salt { set; get; }

        /// <summary>
        /// 是否冻结
        /// </summary>
        public bool IsFrozen { set; get; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { set; get; }
    }
}

经过多次测试发现,每次只在一台从服务器上面进行读取,纳闷

后来输出发现

Console.WriteLine(con.ClientConnectionId);

连接ID一样,重新启动,刚连接ID会有变动,然后果另一个从服务器进行大量读取。

初步猜测,应该是连接池的搞的鬼,如果关闭连接,但是实际上,并没有关闭数据库连接,而是归还连接池。重新打开数据库,又重连接池分配一条连接。

目前不清楚连接池的分配规则,从结果来看,应该是每次都是分配了相同的程序池连接。

现在暂进不测了,下班走,改天,部署WEB结构,然后用压力测试测试,看看数据库读取是否均衡。

原文地址:https://www.cnblogs.com/NET-BLOG/p/8308506.html

时间: 2024-10-01 18:20:01

windows NLB实现MSSQL读写分离--从数据库集群读负载均衡的相关文章

构建读写分离的数据库集群

4.1实战案例——构建读写分离的数据库集群 使用Mycat作为数据库中间件服务构建读写分离的数据库集群 使用一台虚拟机部署Mycat数据库中间件服务,将用户提交的读写操作识别分发给相应的数据库 节点.这样将用户的访问操作.数据库的读与写操作分给3台主机,只有数据库集群的主节点接 收增.删.改SQL语句,从节点接收查询语句,分担了主节点的查询压力 基础准备 使用CentOS 7.2系统,创建3台虚拟机进行实验. 其中2台虚拟机db1和db2部署MariaDB数据库服务,搭建主从数据库集群:一台作为

数据库双重负载均衡读写分离及双活集群

双重负载均衡读写分离及双活集群 ---数据库性能和容灾一体化解决方案 说明: 1. 第一重负载均衡读写分离:节点DB-A和DB-B之间负载均衡和读写分离,数据同步方式为同步模式. 2. 第二重负载均衡读写分离:节点DB-C执行报表.OLAP查询等,数据同步方式为异步模式. 3. 双活集群:两节点DB-A和DB-B构成双活集群(故障时数据零丢失.服务不停止). 4. 兼容性:客户端代码零修改,和原本单机数据库访问保持二进制兼容.

负载与读写分离图片服务器集群模型

对于绝大多数网站,图片资源是一个非常重要的元素.社区论坛里面图片相册,电子商务线上产品展示图,移动端应用图片分享功能等.都在说互联网正在处于读图时代,各大中小型网站都需要保持良好的图片处理能力.需要支持海量图片资源存储时,更加要搭建高可用负载图片服务集群支撑网站系统,保证网站上图片相关功能准确无误运行,用户对象访问页面体验流畅. 环境:四台Linux主机,一台LVS负载均衡,一台FastDFS_tracker,两台FastDFS_storage,FastDFS_client在FastDFS_tr

mysql+mycat搭建稳定高可用集群,负载均衡,主备复制,读写分离

主要思路 测试环境 实现mysql主备复制 配置A主mysql 配置B备mysql 验证同步配置结果 验证是否同步 关闭B备mysql的同步,验证读写分离 实现读写分离 安装mycat 配置mycat 启动mycat 测试读写分离 验证是否同步 关闭B备mysql的同步,验证读写分离 数据库性能优化普遍采用集群方式,oracle集群软硬件投入昂贵,今天花了一天时间搭建基于mysql的集群环境. 主要思路 简单说,实现mysql主备复制-->利用mycat实现负载均衡. 比较了常用的读写分离方式,

mysql+myca搭建稳定高可用集群,负载均衡,主备复制,读写分离

数据库性能优化普遍采用集群方式,oracle集群软硬件投入昂贵,今天花了一天时间搭建基于mysql的集群环境. 主要思路 简单说,实现mysql主备复制-->利用mycat实现负载均衡. 比较了常用的读写分离方式,推荐mycat,社区活跃,性能稳定. 测试环境 MYSQL版本:Server version: 5.5.53,到官网可以下载WINDWOS安装包. 注意:确保mysql版本为5.5以后,以前版本主备同步配置方式不同. linux实现思路类似,修改my.cnf即可. A主mysql.19

DB层面上的设计 分库分表 读写分离 集群化 负载均衡

第1章  引言 随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题.对于一个大型的 互联网应用,每天几十亿的PV无疑对数据库造成了相当高的负载.对于系统的稳定性和扩展性造成了极大的问题.通过数据切分来提高网站性能,横向扩展数据层 已经成为架构研发人员首选的方式.水平切分数据库,可以降低单台机器的负载,同时最大限度的降低了了宕机造成的损失.通过负载均衡策略,有效的降低了单台 机器的访问负载,降低了宕机的可能性:通过集群方案,解决了数据库宕机带来的单点数据库不能访问的问题:通过读

数据库水平切分的实现原理(分库,分表,主从,集群,负载均衡)

第1章  引言 随着互联网应用的广泛普及,海量数据的存储和访问成为了系统设计的瓶颈问题.对于一个大型的 互联网应用,每天几十亿的PV无疑对数据库造成了相当高的负载.对于系统的稳定性和扩展性造成了极大的问题.通过数据切分来提高网站性能,横向扩展数据层 已经成为架构研发人员首选的方式.水平切分数据库,可以降低单台机器的负载,同时最大限度的降低了了宕机造成的损失.通过负载均衡策略,有效的降低了单台 机器的访问负载,降低了宕机的可能性:通过集群方案,解决了数据库宕机带来的单点数据库不能访问的问题:通过读

15套java互联网架构师、高并发、集群、负载均衡、高可用、数据库设计、缓存、性能优化、大型分布式 项目实战视频教程

* { font-family: "Microsoft YaHei" !important } h1 { color: #FF0 } 15套java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  cloud.Dubbo.Redis.ActiveMQ.Nginx.Mycat

简单使用Mysql-Cluster-7.5搭建数据库集群

阅读目录 前言 mysql cluster中的几个概念解释 架构图及说明 下载mysql cluster 安装mysql cluster之前 安装配置管理节点 安装配置数据和mysql节点 测试 启动和关闭 总结 |前言 当你的业务到达一定的当量,肯定需要一定数量的数据库来负载均衡你的数据库请求,我在之前的博客中已经说明了,如何实现负载均衡,但是还有一个问题就是数据同步,因为负载均衡的前提就是,各个服务器的数据库是数据同步的.在业务量不大的时候,我们会使用主从复制的方法实现服务器数据同步,一主多