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)

本地發佈dom

通常而言,咱們只須要安裝數據庫引擎服務便可。複製服務須要另外安裝,因此咱們進行發佈/訂閱模式的話,須要安裝複製組件ide

192.168.99.250 主服務器發佈數據同步,接三臺從服務器訂閱發佈。post

本地訂閱測試

一樣本地訂閱,也須要安裝複製組件。ui

 

模擬寫數據加密

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集羣spa

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結構,而後用壓力測試測試,看看數據庫讀取是否均衡。

相關文章
相關標籤/搜索