一些感谢的话
首先,自然是要感谢 “路过秋天” 对CYQ.Data的开源(当然,不仅仅是CYQ.Data喔。看他的架势,那是准备凑齐黄金十二宫的)
路过秋天Blog地址[里面有更多他的开源项目]:http://www.cnblogs.com/cyq1162/
左侧公告的两个二维码分别是他的创业公众号和创业项目[IT连APP],有兴趣的朋友可以扫码喔
------------------------------------------------------------------------------------------------------------------------
我接触CYQ.Data没几天,为了项目重构,想找一个集成数据操作,分布式缓存,数据库读写分离的框架。于是乎,我就看到了……
昨晚,在测试读写分离的执行机制时,遇到一些问题。于是第一时间联系了秋天本人。令我敬佩的是,二话没说,一一解决。我测他改,俩人折腾到大半夜,才算完功。于是才有了本文
我想说,在当今浮躁的时代,为一个原本素不相识的人,能够有如此耐心。实属难得
好了,一些感慨就算是完了,下面是正餐
CYQ.Data(V5) 数据库读写分离入门
为了一些未使用过CYQ.Data的朋友们能够更好的了解,这里先说一些基础的
1:配置规则
以MSSQL为例
<add name="Conn" connectionString="server=.;uid=sa;pwd=123456;database=db;" providerName="System.Data.SqlClient"/> <add name="Conn_Bak" connectionString="server=.;uid=sa;pwd=123456;database=db_back;" providerName="System.Data.SqlClient"/> <add name="Conn_Slave1" connectionString="server=.;uid=sa;pwd=123456;database=db_Slave1;" providerName="System.Data.SqlClient"/> <add name="Conn_Slave2" connectionString="server=.;uid=sa;pwd=123456;database=db_Slave2;" providerName="System.Data.SqlClient"/> <add name="Conn_Slave3" connectionString="server=.;uid=sa;pwd=123456;database=db_Slave3;" providerName="System.Data.SqlClient"/>
其中:
Conn:主数库连接配置[可写](以下简称主库)
Conn_Bak:备份数库连接配置[可写](以下简称备库)
Conn_Slave1……Conn_SlaveN:从库数库连接配置[只读](以下简称从库)
2:执行机制
2.1:如何启用读写分离
当配置节中存在至少一个 [从库] 项时,即启用读写分离机制
2.2:写操作
2.2.1:遵循:主~备的切换顺序
2.2.2:主库和备库在做写操作时,按先主后备的顺序执行。当主库宕机以后,框架自动切换至备库
2.2.3:当备库也宕机时,写操作的请求将中止。假如你配置了从库,也不用担心,它们将不受任何影响
2.3:读操作
遵循:从~主~备的顺序。任何一个节点的数据库发生意外,框架将按配置项请求下一个有效连接
3:常规应用场景
最直接的目的当然是为了数据库的分流。我们常说的分布式数据库架构中都可以使用它做为数据层来完成。类似于分库,分表之类的操作;简单的说,当你为了减轻数据库压力,需要多个库操作时,就有它的用武之地
4:简单示例浅析
比如说,有一个文章系统,最核心的数据就是发布的文章。我们可以使用当前很常规的方式采用生成静态的.html文件来缓解数据库的实时请求压力;但是文章数目的上限是不可控的,存储空间,单服务器的承载能力这些都是不可控的因素。
这时,我们的负载均衡就可以闪亮登场了。那么随之而来的就有一个问题,既然已经部署了多服务器的负载均衡,数据库呢?数据库怎么办?
最粗暴的当然还可以直接使用单数据库。但显然,我们还能有更好的解决方案。这就是:数据分布式架构
我们通过主数据库的分发,其他数据库的订阅来达到各服务器之间的数据(完全或指定部份)一致
分布式的架构的部署就带来一个新的需求,我们需要每一个数据库都做出贡献,而不单单是做为数据备份存在。基于这种需求,CYQ.Data 就可以完美的完成你的业务需求
最简单的方式:我们可以在数据库~生成的.html页面之间,加入CYQ.Data。当一个请求发出时,如果当前服务器不存在对应的html页面,从数据库中获取数据,生成页面,返回前端。[关于页面数据发生变化,需要重新生成时,由其他业务完成,这里我们按下不表]
那当页面不存在时,我们是需要从数据库获取数据的。但现在我们有若干个数据库,如何合理的从这些库中获取数据呢?很简单:使用CYQ.Data,配置好 主~备~从 规则即可 [配置方法以及执行机制往上看]
5:代码使用
读数据:
string json; using (MAction action = new MAction("表名")) { json = action.Select().ToJson(); }
在config中配置好主~备~从节点以后,以上的代码就可以轻易的从数据库中获取指定表的数据了[关于读写分离中读操作的执行机制,往上看];一切如此简单;无需任何复杂的业务代码,一切都由CYQ.Data帮您完成了
写数据[以Update为例]:
using (MAction action = new MAction("表名")) { action.SetExpression("a=1"); action.Update("id=1"); }
和读操作一样,配置好节点以后,就可以按其执行机制去完成对数据的更新了。再次说一句:一切如此简单
除 MAction 以外,框架还提供了 MProc 去调用存储过程。具体用法类似,这里就不再赘述
上面的例子,针对的是主~备~从三种库的结构相同时的情况。那如果从库的表与主库的并不一致时呢?比如现在需要请求:表A,但从库中并没有表A,它或许只存在于主备库中,这时,请求的结果将发生意外。于是对于子业务模块的读写分离我们也需要有对应的解决方案;这就是今天的彩蛋和亮点了
实现子模块的读写分离[分库分表]
功能的实现简单到你难以想像。以下示例配置为:对文章表做了垂直切分,不与主库在一起了。所以Article系列的从库只保存了文章
1:配置
<add name="ArticleConn" connectionString="设置为主库连接" providerName="System.Data.SqlClient"/> <add name="ArticleConn_Slave1" connectionString="server=.;uid=sa;pwd=123456;database=ArticleDb_Slave1;" providerName="System.Data.SqlClient"/> <add name="ArticleConn_Slave2" connectionString="server=.;uid=sa;pwd=123456;database=ArticleDb_Slave1;" providerName="System.Data.SqlClient"/> <add name="ArticleConn_Slave3" connectionString="server=.;uid=sa;pwd=123456;database=ArticleDb_Slave3;" providerName="System.Data.SqlClient"/>
2:代码
string json; //将配置Key:ArticleConn做为参数传入 //接下来的请求中就将以ArticleConn做为主库,使用配置中的ArticleConn_Slave1……ArticleConn_SlaveN的主从关系实现读数据 using (MAction action = new MAction("Article", "ArticleConn")) { json = action.Select().ToJson(); }
一个参数的传入,就解决了;ArticleConn 作为主库的配置在读数据时并不产生任何作用。在写操作时,不传入这个参数,即可使用主库[Conn]的连接
using (MAction action = new MAction("Article")) { action.SetExpression("a=1'"); action.Update("id=1"); }
模块化的读写分离需求场景
以现成的博客园为例,我们可以将用户,文章,评论,三大模块分开存放。各自建立 主~备~从 关系。在这个基础上,我们可以对每个模块的数据进行水平拆分,使用语句或视图进行聚合;这样的性能和效率,远不是单机单库可以相比的。当然,前提是你有足够的的Money~~~哈哈哈
其实今天本想把重点放在后半部份的,但想着想着发现,其实一切都很强大。所以最后也只是以一种应用场景的方式列出来了
最后,还得说一次:一切如此简单,你还在等什么呢?有兴趣的朋友去秋天大神的blog中下载呀