前言:
继上一篇, 介绍 CYQ.Data https://github.com/cyq1162/cyqdata 在分布式缓存上支持高可用, 详见: CYQ.Data 对于分布式缓存 Redis,MemCache 高可用的改进及性能测试
本篇介绍 CYQ.Data 在对数据库层面对分布式数据库的主从备的高可用的及负载调度.
目前框架支持的数据库 (及缓存) 种类为:
Support:Txt,xml,Access,SQLite,Mssql,MySQL,Oracle,Sybase,Postgres,Redis,MemCache.
下面就开始介绍:
1, 数据库集群与负载的高可用:
1, 集群与故障转移
想当年, 在北京联通的项目上, 为了实现数据库集群故障转移, 那可是一堆人在机房折腾的死去活来.
还要开什么研论会, 要机房, 网络设计人员, 和项目层面的三方人码动手.
折腾到最后的结果, 浪费了一台服务器做热备.
2, 由客户端调度主从备, 实现故障转移与负载.
CYQ.Data 在很早前, 就实现了主从备的切换了, 只是没有实现高可用.
这一次, 迎合 NET Core 在未来分布式应用下的需求, 补上了这个功能.
2,CYQ.Data 在分布式下的数据库可高用:
下面来看简单的使用过程:
1, 指定配置外链:
原有的配置:
- <connectionStrings>
- <add name="Conn" connectionString="server=.;database=test;uid=sa;pwd=123456"
- />
- <add name="Conn_Bak" connectionString="server=.;database=test;uid=sa;pwd=123456"
- />
- <add name="Conn_Slave1" connectionString=".;database=test;uid=sa;pwd=123456"
- />
- <add name="Conn_Slave2" connectionString="server=.;database=demo;uid=sa;pwd=123456"
- />
- </connectionStrings>
将配置写在原的 config 中, 是当修改时, 会引发 (Windows 下) 整个程序重启(而 NetCore 默认不重启, 需要特殊处理配置文件重新加载事件).
改进后配置(文件后缀可以指定 *.INI,*.txt, *.JSON):
<add name="Conn" value="conn.json"/>
对应的 conn.JSON 文件:
- {
- "Conn": {
- "Master": "server=.;database=demo;uid=sa;pwd=123456",
- "Backup": "server=.;database=test;uid=sa;pwd=123456",
- "Slave": [
- "server=.;database=test;uid=sa;pwd=123456",
- "server=.;database=demo;uid=sa;pwd=123456"
- ]
- }
- }
将配置外置后, 程序会自动监控文件的变化, 每次修改都会即时生效, 内部自动调整算法, 实现高可用.
配置后好, 剩下的问题就是你有多少台服务器可以安装数据库实例了.
2, 数据库主从备的机制说明:
主备: 当主库发生故障时, 会自动切换到备库.
主从: 主库负责写, 从库负责读.
3, 关于读的负载调度:
只要是被加入 Slave 的链接, 都会顺序被执行.
因此, 如果写的任务不多, 可以把主库的链接也加入到 Slave 中, 分担读的压力.
再把备库的链接都加载入到 Slave 中, 反正备库平时也用不上, 一样可以继续分担读的压力.
另外, Slave 由于是顺序调度, 所以要加大某实例的负载时, 可以将该实例的链接复制多份, 以提高被执行的概率.
因此, 只要配合服务器性能监控, 再动态修改链接指向的配置文件, 即可实现高可用的性能负载.
下面来做一个测试实验:
3, 主从备负载切换的实验:
首先, 创建了五个数据库: MasterDB,BackupDB,SlaveDB1,SlaveDB2,SlaveDB2.
然后: 数据库间的同步, 这一步就先省了.
写测试代码, 运行两个线程, 分别是读与写:
- public class MasterBackupSlave
- {
- public static void Start()
- {
- AppConfig.Log.LogConn = "Conn";
- ThreadPool.QueueUserWorkItem(new WaitCallback(Read), "Read");
- ThreadPool.QueueUserWorkItem(new WaitCallback(Write), "Write");
- Console.Read();
- }
- private static void Read(object threadFlag)
- {
- while (true)
- {
- using (SysLogs logs = new SysLogs())
- {
- logs.Fill(1);
- Console.WriteLine("Read :" + ((MAction)logs).DataBase);
- }
- Thread.Sleep(1000);
- }
- }
- private static void Write(object threadFlag)
- {
- while (true)
- {
- using (SysLogs logs = new SysLogs())
- {
- logs.Message = Guid.NewGuid().ToString();
- logs.Insert();
- Console.WriteLine("--------------Write :" + ((MAction)logs).DataBase);
- }
- Thread.Sleep(1000);
- }
- }
- }
然后运行, 看到以下输出, 写在主库, 读在从库中切换:
接着, 我们测试主备, 把主库弄挂了, 这时会切到从, 再把主库恢复, 这时候会切回来.
最后, 我们随时减少或增加从库负载的实例:
没错, 和分布式缓存一样, 框架已经从单机的应用, 向分布式高负载和高可用性进化了.
总结:
别问我为什么, 总之, 就是这么强大.
来源: https://www.cnblogs.com/cyq1162/p/10651706.html