《PHP實戰(zhàn):Yii實現(xiàn)MySQL多數(shù)據(jù)庫和讀寫分離實例分析》要點:
本文介紹了PHP實戰(zhàn):Yii實現(xiàn)MySQL多數(shù)據(jù)庫和讀寫分離實例分析,希望對您有用。如果有疑問,可以聯(lián)系我們。
PHP編程本文實例分析了Yii實現(xiàn)MySQL多數(shù)據(jù)庫和讀寫分離的辦法.分享給大家供大家參考.具體分析如下:
PHP編程Yii Framework是一個基于組件、用于開發(fā)大型 Web 應用的高性能 PHP 框架.Yii提供了今日Web 2.0應用開發(fā)所需要的幾乎一切功能,也是最強大的框架之一,下文我們來介紹Yii實現(xiàn)MySQL多庫和讀寫分離的辦法
PHP編程前段時間為SNS產(chǎn)品做了架構(gòu)設計,在程序框架方面做了不少相關的壓力測試,最終選定了YiiFramework,至于為什么沒選用公司內(nèi)部的 PHP框架,其實理由很充分,公司的框架雖然是"前輩"們辛苦的積累,但畢竟不夠成熟,沒有大型項目的歷練,猶如一個涉世未深的年輕小伙.Yii作為一個 頗有名氣開源產(chǎn)品,必定有很多人在使用,意味著有一批人在維護,而且在這之前,我也使用Yii開發(fā)過大型項目,Yii的設計模式和它的易擴展特性足以堪當重任.
PHP編程SNS同一般的社交產(chǎn)品不同的就是它最終要承受大并發(fā)和大數(shù)據(jù)量的考驗,架構(gòu)設計時就要考慮這些問題, web分布式、負載均衡、分布式文件存儲、MySQL分布式或讀寫分離、NoSQL以及各種緩存,這些都是必不可少的應用方案,本文所講的就是MySQL 分庫和主從讀寫分離在Yii的配置和使用.
PHP編程Yii默認是不支持讀寫分離的,我們可以利用Yii的事件驅(qū)動模式來實現(xiàn)MySQL的讀寫分離.
PHP編程Yii提供了一個強大的CActiveRecord數(shù)據(jù)庫操作類,通過重寫getDbConnection辦法來實現(xiàn)數(shù)據(jù)庫的切換,然后通過事件 beforeSave、beforeDelete、beforeFind 來實現(xiàn)讀寫服務器的切換,還需要兩個配置文件dbconfig和modelconfig分別配置數(shù)據(jù)庫主從服務器和model所對應的數(shù)據(jù)庫名稱,附代碼
DBConfig.php文件如下:
代碼如下:
<?php
return array(
'passport' => array(
'write' => array(
'class' => 'CDbConnection',
'connectionString' => 'mysql:host=10.1.39.2;dbname=db1′,
'emulatePrepare' => true,
//'enableParamLogging' => true,
'enableProfiling' => true,
'username' => 'root',
'password' => '',
'charset' => 'utf8′,
'schemaCachingDuration'=>3600,
),
'read' => array(
array(
'class' => 'CDbConnection',
'connectionString' => 'mysql:host=10.1.39.3;dbname=db1,
'emulatePrepare' => true,
//'enableParamLogging' => true,
'enableProfiling' => true,
'username' => 'root',
'password' => '',
'charset' => 'utf8′,
'schemaCachingDuration'=>3600,
),
array(
'class' => 'CDbConnection',
'connectionString' => 'mysql:host=10.1.39.4;dbname=db3′,
'emulatePrepare' => true,
//'enableParamLogging' => true,
'enableProfiling' => true,
'username' => 'root',
'password' => '',
'charset' => 'utf8′,
'schemaCachingDuration'=>3600,
),
),
),
);
ModelConfig.php如下:
代碼如下:
<?php
return array(
//key為數(shù)據(jù)庫名稱,value為Model
'passport' => array('User','Post'),
'microblog' => array('…'),
);
?>
ActiveRecord.php如下:
代碼如下:
/**
* 基于CActiveRecord類的封裝,實現(xiàn)多庫和主從讀寫分離
* 所有Model都必須繼承些類.
*
*/
class ActiveRecord extends CActiveRecord
{
//model配置
public $modelConfig = '';
//數(shù)據(jù)庫配置
public $dbConfig = '';
//定義一個多數(shù)據(jù)庫集合
static $dataBase = array();
//當前數(shù)據(jù)庫名稱
public $dbName = '';
//定義庫類型(讀或?qū)?
public $dbType = 'read'; //'read' or 'write'
/**
* 在原有基礎上添加了一個dbname參數(shù)
* @param string $scenario Model的應用場景
* @param string $dbname 數(shù)據(jù)庫名稱
*/
public function __construct($scenario='insert', $dbname = '')
{
if (!empty($dbname))
$this->dbName = $dbname;
parent::__construct($scenario);
}
/**
* 重寫父類的getDbConnection辦法
* 多庫和主從都在這里切換
*/
public function getDbConnection()
{
//如果指定的數(shù)據(jù)庫對象存在則直接返回
if (self::$dataBase[$this->dbName]!==null)
return self::$dataBase[$this->dbName];
if ($this->dbName == 'db'){
self::$dataBase[$this->dbName] = Yii::app()->getDb();
}else{
$this->changeConn($this->dbType);
}
if(self::$dataBase[$this->dbName] instanceof CDbConnection){
self::$dataBase[$this->dbName]->setActive(true);
return self::$dataBase[$this->dbName];
} else
throw new CDbException(Yii::t('yii','Model requires a "db" CDbConnection application component.'));
}
/**
* 獲取配置文件
* @param unknown_type $type
* @param unknown_type $key
*/
private function getConfig($type="modelConfig",$key="){
$config = Yii::app()->params[$type];
if($key)
$config = $config[$key];
return $config;
}
/**
* 獲取數(shù)據(jù)庫名稱
*/
private function getDbName(){
if($this->dbName)
return $this->dbName;
$modelName = get_class($this->model());
$this->modelConfig = $this->getConfig('modelConfig');
//獲取model所對應的數(shù)據(jù)庫名
if($this->modelConfig)foreach($this->modelConfig as $key=>$val){
if(in_array($modelName,$val)){
$dbName = $key;
break;
}
}
return $dbName;
}
/**
* 切換數(shù)據(jù)庫連接
* @param unknown_type $dbtype
*/
protected function changeConn($dbtype = 'read'){
if($this->dbType == $dbtype && self::$dataBase[$this->dbName] !== null)
return self::$dataBase[$this->dbName];
$this->dbName = $this->getDbName();
if(Yii::app()->getComponent($this->dbName.'_'.$dbtype) !== null){
self::$dataBase[$this->dbName] = Yii::app()->getComponent($this->dbName.'_'.$dbtype);
return self::$dataBase[$this->dbName];
}
$this->dbConfig = $this->getConfig('dbConfig',$this->dbName);
//跟據(jù)類型取對應的配置(從庫是隨機值)
if($dbtype == 'write'){
$config = $this->dbConfig[$dbtype];
}else{
$slavekey = array_rand($this->dbConfig[$dbtype]);
$config = $this->dbConfig[$dbtype][$slavekey];
}
//將數(shù)據(jù)庫配置加到component中
if($dbComponent = Yii::createComponent($config)){
Yii::app()->setComponent($this->dbName.'_'.$dbtype,$dbComponent);
self::$dataBase[$this->dbName] = Yii::app()->getComponent($this->dbName.'_'.$dbtype);
$this->dbType = $dbtype;
return self::$dataBase[$this->dbName];
} else
throw new CDbException(Yii::t('yii','Model requires a "changeConn" CDbConnection application component.'));
}
/**
* 保存數(shù)據(jù)前選擇 主 數(shù)據(jù)庫
*/
protected function beforeSave(){
parent::beforeSave();
$this->changeConn('write');
return true;
}
/**
* 刪除數(shù)據(jù)前選擇 主 數(shù)據(jù)庫
*/
protected function beforeDelete(){
parent::beforeDelete();
$this->changeConn('write');
return true;
}
/**
* 讀取數(shù)據(jù)選擇 從 數(shù)據(jù)庫
*/
protected function beforeFind(){
parent::beforeFind();
$this->changeConn('read');
return true;
}
/**
* 獲取master庫對象
*/
public function dbWrite(){
return $this->changeConn('write');
}
/**
* 獲取slave庫對象
*/
public function dbRead(){
return $this->changeConn('read');
}
}
PHP編程這是我寫好的類,放在components文件夾里,然后所有的Model都繼承ActiveRecord類就可以實現(xiàn)多庫和主從讀寫分離了,至于如何支持原生的SQL也同時使用讀寫分離,此類都已經(jīng)實現(xiàn).
PHP編程希望本文所述對大家基于Yii框架的PHP程序設計有所贊助.
維易PHP培訓學院每天發(fā)布《PHP實戰(zhàn):Yii實現(xiàn)MySQL多數(shù)據(jù)庫和讀寫分離實例分析》等實戰(zhàn)技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養(yǎng)人才。
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.snjht.com/jiaocheng/13495.html