Home >Database >Mysql Tutorial >.NET实现数据库读写分离(SQLSERVER2005,ORACLE)

.NET实现数据库读写分离(SQLSERVER2005,ORACLE)

WBOY
WBOYOriginal
2016-06-07 15:34:29843browse

随着业务量的提高,以及访问量和数据流量的快速增长,网络各个核心部分的处理性能和计算强度也相应增大,使得单一设备根本无法承担。在此情况下,如果扔掉现有设备去做大量的硬件升级,必将造成现有资源的浪费,而且下一次业务量的提升,又将导致再一次硬件升

随着业务量的提高,以及访问量和数据流量的快速增长,网络各个核心部分的处理性能和计算强度也相应增大,使得单一设备根本无法承担。在此情况下,如果扔掉现有设备去做大量的硬件升级,必将造成现有资源的浪费,而且下一次业务量的提升,又将导致再一次硬件升级的高额成本投入。于是,负载均衡机制应运而生。

对于负载均衡,笔者经常接触的当属Oracle的负载均衡机制。下面,我们先简单了解Oracle的负载均衡的实现方案。

Real Application Clusters是双机并行服务器(8i及以前版本称作Oracle Parallel Server,OPS),用来在集群环境下实现多机共享数据库,以保证应用的高可用性,同时可以自动实现并行处理及均分负载,还能实现数据库在故障时的排错和无断点恢复。它可以自动进行负载平衡、故障修复和规划停机时间,以支持高可用性应用程序。若并行服务器中某节点失效,透明的应用程序容错能够把用户自动转接到另一节点上继续运行,应用程序在用户没有察觉的情况下继续执行。这使周期性和非周期性发生故障的系统增大了连续可用性。进程的失效可以完全透明地转移到另一节点上去,通过适当地配置,可以指定所有查询都在客户端进行缓存,这样它们便可以在转移后的节点上重新设置。

下面我们重点介绍Sql Server 2005是如何实现负载均衡的。

 

Sql Server 2005的新特性

 

端到端拓扑的事务性复制

SQL Server 2005对端到端(P2P)拓扑结构上事务性的复制加强了支持。P2P的拓扑结构支持无限的发布服务器,它们彼此之间可以互相交换事务。

P2P拓扑是SQL Server的一个巨大进步。现在,多端点服务器可以更改数据,并且向其他的发布者复制事务。这就是说,订阅服务器不再被限制在主要的报告环境中,可以通过事务性负载全球共享的方式将服务器分布开来。当用户的数量增加的时候,只要简单地向这个群体中添加服务器即可。

除了将负载分布之外,这个拓扑结构还增加了可用性。如果任何一个点的服务器不可达,则池中其他服务器就会共享这个负载,因为每个服务器都有其他所有服务器上可获得的全部数据集合。

 

数据库镜像和快照

SQL Server 2005引入了数据库镜像的概念,来帮助获得高可用性。特别提醒的是,只要它正式发布了,数据库镜像就可以在SQL Server 2005上使用。然而,只有到SQL Server 2005 Service Pack 1才会支持镜像。

数据库快照是SQL Server 2005中引入的另一项特性。快照是某一个时间点上的数据库的克隆。只要对镜像数据库进行了快照,就可以让用户查询快照。快照的生成通常只需要几秒钟,因为它实际上在这个过程中并没有拷贝任何数据。因此,要把负载分布到主服务器和备用服务器上,就可以将数据库做镜像,然后阶段性地对备份服务器进行快照。而且还可以使用快照在主服务器上进行报告。

 

软件实现SQL Server 2005的负载均衡

 

中间层

实现数据库的负载均衡技术,首先要有一个可以控制连接数据库的控制端。在这里,它截断了数据库和程序的直接连接,由所有的程序来访问这个中间层,然后再由中间层来访问数据库。这样,我们就可以具体控制访问某个数据库了,然后还可以根据数据库的当前负载来调整每次连接到哪个数据库。好处在两个方面:首先,它成功地将数据库放到了内网之中,更好地保护了数据库的安全性。如果数据库也在公网上,1433端口是很容易被攻击的,所以要保护数据库与之的连接,就用到了中间层。它可以将数据库更加好地保护在内网。其次,连接数据库的所有连接都可以控制,更方便DBA对数据的管理,看哪些连接更耗费数据库资源,以便更好地优化代码。

但是,也有两点要注意:第一,必须要做成Windows的服务程序。Windows发展到今天,如果以一个集成的大系统来讲,做成服务程序更加稳定,也更加安全,这样做即使用户不登录机器,也可以使用。第二,必须要使用多个中间层。从中间层的作用可以看出,它承接了数据库的所有连接,所以,一旦出了问题,就会导致整个系统瘫痪。所以做多个中间层是必要的,这样,如果一个坏了可以登录到另一个。

 

实现多据库数据同步

中间层有了,下一步的工作是设置构建数据库集群。对于负载均衡,最重要的就是所有服务器的数据都是同步的。这是一个集群所必需的,因为,如果数据不同步,那么用户从一台服务器读出的数据,就有别于从另一台服务器读出的数据,这是不能允许的。所以必须实现一个数据库的数据同步。这里设置一个用于写入的数据库,设置两个用于读出的数据库,因为据统计,一般来讲,70%的数据库操作为读操作。

首先,在写入数据库上做一个发布服务器,主要基于SQL Server 2005的复制技术,将即将用到的表都选上。注意,在连接上要选用模拟用户,然后共享时选择sa用户,这样就可以将数据共享了。

其次,在两个读服务器上做订阅服务,要注意同样的事项,这样一个“一写两读”的数据库集群就完成了。

 

数据库的安全备份

在一个大的系统中,系统的无故障性是很重要的,但是在刚才的系统下,如果用于写的服务器突然坏了,整个系统就会出现问题,所以,再做个备份是必要的。

数据库镜像是SQL Server 2005大力推出的,它就是要实现数据库的安全转移,所以需要再单独拿出一台机器来做备份服务器,将完全镜像写入该服务器,这样,即使写入服务器坏了,它也可以自动转移到备份服务器上来,保证不影响用户。

这实际上就相当于实现了对服务器的容灾管理,但是有一点需要注意,在这种镜像的体系中,必须要有一台服务器作为监视服务器,以便察看哪台服务器坏了,用以在机器出错之后迅速调整。

 

回传数据库的状态

数据库服务器均已配完,整体的机器集群架构已经构建,接下来的工作就是配置程序。

首先,在读和写的服务器都放上一个监控程序,它同样必须是Windows的服务,这样更稳定;其次,它可以设定成每隔30秒或者一定时间,将服务器的CPU、内存、网卡流量和当前数据库状态等信息发送回来。在这里需要设置一个权值,用以衡量CPU、内存利用率等信息的各自比例。在这个系统中,建议以CPU利用率为准。

 

中间层实现的负载均衡

到此为止,所有的准备工作都已完成,包括数据库的建立和配置,中间层的位置,下面所作的就是用软件来实现这个负载均衡。

首先,当一个用户有数据库请求时,先判断是读还是写,如果是写的话,就直接返回写入服务器,这样当写服务器写完数据以后,差不多可以在3秒内返回其他两台机器。

其次,当遇到一个读的请求时,根据监控返回来的数据判断,根据刚才的权值返回一个当前最空闲的机器。需要注意的是,这时最好做一个记录器,用以保持一段时间的数值,可以让管理员自行设定,更好地做到几台数据库的压力平衡。

最后,如果为主的写入服务器突然坏掉,程序可以自动把备份的服务器切换过来,用刚才的备份服务器当作写服务器,然后做一个报警系统,用以通知管理员。同样,当监控服务器发现其他两台读服务器坏掉时,也会自动通知管理员,来处理服务器的异常情况,这样就可以保证系统的稳定运行,而且易于管理和维护。

总之,用软件和微软SQL Server 2005的一些新技术,可以很轻松地实现负载均衡,这样不但可以不用硬件来实现,方便管理员的操控,更有利于DBA管理数据库,及时发现问题。

.NET实现数据库读写分离(SQLSERVER2005,ORACLE)

代码

<span>///</span> <span><summary></summary></span>
    <span>///</span><span> 数据库服务工厂
    </span><span>///</span><span> 版本:2.0
    </span><span>///</span> <span><author></author></span>
    <span>///</span>        <span><name></name></span><span>shecixiong</span><span></span>
    <span>///</span>        <span><date></date></span><span>2013.05.28</span><span></span>
    <span>///</span> <span></span>
    <span>///</span> <span></span>
    <span>public</span> <span>class</span><span> DataFactory
    {
        </span><span>///</span> <span><summary></summary></span>
        <span>///</span><span> 从配置信息获取连接字符串
        </span><span>///</span> <span></span>
        <span>///</span> <span><param name="key"></span>
        <span>///</span> <span><returns></returns></span>
        <span>private</span> <span>static</span> <span>string</span> GetConfig(<span>string</span><span> key)
        {
            </span><span>return</span><span> ConfigHelper.GetAppSettings(key);
        }
        </span><span>///</span> <span><summary></summary></span>
        <span>///</span><span> 链接 SqlServer 数据库
        </span><span>///</span><span> 操作写入
        </span><span>///</span> <span></span>
        <span>///</span> <span><returns></returns></span>
        <span>public</span> <span>static</span><span> IDbHelper SqlServerRead()
        {
            </span><span>return</span> <span>new</span> SqlServerHelper(GetConfig(<span>"</span><span>SqlServer_IP_Read</span><span>"</span><span>));
        }
        </span><span>///</span> <span><summary></summary></span>
        <span>///</span><span> 链接 SqlServer 数据库
        </span><span>///</span><span> 操作读取
        </span><span>///</span> <span></span>
        <span>///</span> <span><returns></returns></span>
        <span>public</span> <span>static</span><span> IDbHelper SqlServerWrite()
        {
            </span><span>return</span> <span>new</span> SqlServerHelper(GetConfig(<span>"</span><span>SqlServer_IP_Write</span><span>"</span><span>));
        }
        </span><span>///</span> <span><summary></summary></span>
        <span>///</span><span> 链接 Oracle 数据库
        </span><span>///</span><span> 操作写入
        </span><span>///</span> <span></span>
        <span>///</span> <span><returns></returns></span>
        <span>public</span> <span>static</span><span> IDbHelper OracleRead()
        {
            </span><span>return</span> <span>new</span> OracleHelper(GetConfig(<span>"</span><span>Oacle_IP_Read</span><span>"</span><span>));
        }
        </span><span>///</span> <span><summary></summary></span>
        <span>///</span><span> 链接 Oracle 数据库
        </span><span>///</span><span> 操作读取
        </span><span>///</span> <span></span>
        <span>///</span> <span><returns></returns></span>
        <span>public</span> <span>static</span><span> IDbHelper OracleWrite()
        {
            </span><span>return</span> <span>new</span> OracleHelper(GetConfig(<span>"</span><span>Oacle_IP_Read</span><span>"</span><span>));
        }
    }
}</span>

App.config

     <!-- 连接字符串是否加密-->
        <add key="<span">"<span>ConStringEncrypt</span><span>"</span> value=<span>"</span><span>false</span><span>"</span>/>
        <!-- 连接字符串-->
        <add key="<span">"<span>SqlServer_IP_Read</span><span>"</span> value=<span>"</span><span>Server=192.168.1.11;Database=RM_DB;Uid=sa;Pwd=qwertyuiop</span><span>"</span>/>
        <add key="<span">"<span>SqlServer_IP_Write</span><span>"</span> value=<span>"</span><span>Server=192.168.1.10;Database=RM_DB;Uid=sa;Pwd=qwertyuiop</span><span>"</span>/>
        <add key="<span">"<span>Oacle_IP_Read</span><span>"</span> value=<span>"</span><span>Data Source=IP1;User ID=system;Password=qwertyuiop;</span><span>"</span>/>
        <add key="<span">"<span>Oacle_IP_Read</span><span>"</span> value=<span>"</span><span>Data Source=IP2;User ID=system;Password=qwertyuiop;</span><span>"</span>/></add></add></add></add></add>

.NET通用权限系统快速开发框架

 

.NET实现数据库读写分离(SQLSERVER2005,ORACLE).NET实现数据库读写分离(SQLSERVER2005,ORACLE).NET实现数据库读写分离(SQLSERVER2005,ORACLE)

 

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn