zoukankan      html  css  js  c++  java
  • masterslave的实现

    今天本来是想研究一下AR模式的, 可是一不小心, 有陷入了master-slave的实现细节当中.研究之后我决定自己写一个master和slave链接的实现.当然首先让我们一起来看看我们常用的数据库查询需要的语句.

    $connection=Yii::app()->db;

    $command=$connection->createCommand($sql);

    $rowCount=$command->execute();

    标注为红色的地方引起了我的注意,于是有了以下几个想法:

    1) 这个db  明显是Yii 初始化的实例CwebApplication的一个成员变量, 但是在它及它的所有的父类中却找不到db的声明. 直到后来在跟踪查看到CModule中的configure方法时才恍然大悟.

    public function configure($config)

    {

    if(is_array($config))

    {

    foreach($config as $key=>$value)

    $this->$key=$value;

    }

    }

    它竟然用了一个for 循环就把我们在main.php 中所定义的配置变量变成了自己的成员了, 这招实在是精妙.

    2) 于是我就想, 既然db是这样变成成员变量的,那我能不能也照样子在/protected/config/main.php配置一下master 和slave就好了呢.

                           :

            'master' => array( //master db

                'class' => 'CDBConnection',

                'connectionString' => 'mysql:host=127.0.0.1;port=3306;dbname=test',

                'emulatePrepare' => true,

                'username' => 'root',

                'password' => '123',

                'charset' => 'utf8',

                'tablePrefix' => 'ugc_',

                'schemaCachingDuration' => 1,

            ),

            'slave' => array( //slave db

                'class' => 'system.db.CDbConnection',

                'connectionString' => 'mysql:host=127.0.0.1;port=3306;dbname=test',

                'emulatePrepare' => true,

                'username' => 'root',

                'password' => '123',

                'charset' => 'utf8',

                'tablePrefix' => 'ugc_',

                'schemaCachingDuration' => 1,

            ),

                        :

    呵呵, 现在随便在controller的action里边加上这一句看看:

    $connection=Yii::app()->slave;

    ERROR: include(CDBConnection.php) [<a href='function.include'>function.include</a>]: failed to open stream: No such file or directory

    结果却是报错了.为什么它的可以, 我的就不行呢.

    3) 仔细调试发现, 其他的都一样,就是找不到相应的class 文件.于是为CDbConnection 加上路径,结果就没问题了.即:

    CDbConnection 改成 system.db.CDbConnection    这里用到了system的路径别名. 相当于/yii/db/CDbConnection

    OK, 到此为止, 配合我们的mysql的主从同步服务器,  我们便可根据自己的需要选择不同的数据库服务器(一般情况下: 主数据库负责写, 从数据库负责读数据), 以达到读写分离的目的. 从而提升数据库整体的服务能力了, 比如:

    读的时候:

    $connection=Yii::app()->slave;

    $command=$connection->createCommand($sql);

    $rowCount=$command->execute();

    写的时候:

    $connection=Yii::app()->master;

    $command=$connection->createCommand($sql);

    $rowCount=$command->execute();

    说道这里该完了吗? 你也许会问: 你这种方法只是自己在调用的时候明确指定了主从, 那AR模式创建的model里边怎么办?

    好吧,那我们就继续讨论该问题.

    因为所有用Yii工具创建的Model类都继承自CActiveRecord, 所以就想到该在CActiveRecord中找找线索,终于当看到以下这个方法时,突然有了想法.

    public function getCommandBuilder()

    {

    return $this->getDbConnection()->getSchema()->getCommandBuilder();

    }

    对了,就是它.AR 的model在连接数据的时候都是这样来的, 何不将其重新定制一下呢.于是决定在protected/web下新建一个类文件,继承自CActiveRecord.

    <?PHP

    class MyActiveRecord extends CActiveRecord

    {

        private $master = null;

        private $slave = null;

        public function getMasterDbConnection(){

                 if ($this->master!===null)

                          return $this->master;

                 else if ($this->master instanceof CDbConnection)

               return Yii::app()->master;

           else

               throw new CDbException(Yii::t('yii','Active Record requires a "master" CDbConnection application component.'));

         }

        public function getSlaveDbConnection()

            if ($this->slave!===null)

                 return $this->slave;

             else if ($this->slave instanceof CDbConnection)

                   return Yii::app()->slave;

             else

                   throw new CDbException(Yii::t('yii','Active Record requires a "master" CDbConnection application component.'));

        }

        public function getCommandBuilder($master = true) {

                      if ($master)

                                 return $this->getWriteCommandBuilder();                                                                                                                                           return $this->getReadCommandBuilder();                                                                                                                                              }

                                        :

                                        :

                                        :

             注:下边就是把CActiveRecord中的所有读写数据苦的函数复写一遍, 根据读还是写, 调用getCommandBuilder函数选择主从数据库.

    完了之后, 再把生成的model类的父类换成我们自己写的类MyActiveRecord, 这样就算完了.

           补充: 如果修改了父类后, 提示MyActiveRecord没找到, 则在main.php中导入该文件所在的位置;

    'import'=>array(

    'application.models.*',

    'application.components.*',

    'application.web.*',

    ),

    }

    现在应该是没有问题了吧,呵呵.    继续努力, 与君共勉

  • 相关阅读:
    如何手工设置归档目录
    C#字符串格式化说明(String.Format) (zz.IS2120)
    win7 GodMode
    金山软件公司创始人求伯君简介 (is2120.zz)
    【百度地图】安卓系统的百度地图可以下载离线地图,这个很省流量和时间
    手机用笔记本wifi上网【无USB、无软件、无无线路由器】
    安卓版有道词典的离线词库《21世纪大英汉词典》等
    秀秀我的巨无霸手机P1000
    [转载]环游澳大利亚18天——前传与攻略
    [转载]环游澳大利亚18天——前传与攻略
  • 原文地址:https://www.cnblogs.com/xiongsd/p/3054857.html
Copyright © 2011-2022 走看看