1. 程式人生 > 其它 >phalapi-進階篇5(資料庫讀寫分離以及多庫使用)

phalapi-進階篇5(資料庫讀寫分離以及多庫使用)

#phalapi-進階篇5(資料庫讀寫分離以及多庫使用)#

##前言## 先在這裡感謝phalapi框架創始人@dogstar,為我們提供了這樣一個優秀的開源框架.

讀寫分離是我們常用的一種解決方案,它可以解決大量讀操作的時候資料庫瓶頸的問題,我們在真正開發一個專案的過程中可能會遇一個介面或者一個操作中需要用到多個數據庫操作的時候怎麼辦,今天的教程就從這個兩個問題出來,來聊聊使用phalapi怎麼解決這個問題.

附上:

官網地址:http://www.phalapi.net/

開源中國Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release

##1. 讀寫分離##

在我們的生活中無時無刻不面臨這併發的問題,比如下班高峰交通問題,人們用了紅綠燈來解決的一部分問題**(但是很痛苦這個就和查詢的時候阻塞一樣的,10秒做update操作,10秒做select操作一樣的),那麼人們有想到了一個方法高架,高架的路線是和正常的路線一致的(資料相同)** ,高架分兩條路而且一條路上的車不能到另外一條路上**(讀寫分離)** 這樣就解決了我們這類常規併發的問題

其實看起來上面這種解決方案是比較好的其實並不是這樣的,有兩條路但是其實它的寬度是不一樣的,我們這裡把一個叫做寫路,一個叫做讀路,我們如果要做一個讀路並且把他成倍的變寬是一件很簡單的事情(也就是多從庫),但是我們要建立一條寫路可以,但是我們要把這條寫路變寬是比較困難的,我們一般不這樣做.

###1.1 mysql主從配置###

我是使用了阿里雲的多讀庫服務,這裡引用一下百度經驗的mysql主從處理

----------------------------------------------------------------------------------------------------

MYSQL【一臺主機多個例項的主從配置】

1、建立賬號

進入mysql資料庫,建立一個用於從庫備份的賬號

mysql>GRANT REPLICATION SLAVE ON *.* TO 'slave_test'@'10.19.194.57' IDENTIFIED BY 'Password@123456';

mysql>FLUSH PRIVILEGES;   ---重新整理

該命令詳情參考grant建立使用者命令

2、如果已經有一個例項在執行(因為開始已經安裝了mysql,所以有一個預設的),那麼再啟動一個例項,方法如下:

(1)shell>cd /usr/local/mysql/

(2)shell>mkdir -pv /data/mysql2

(3)shell>chown -R mysql.mysql /data/mysql2

(4)shell>./scripts/mysql_install_db  --user=mysql  --datadir=/data/mysql2  這個為另外一個目錄,該步驟意味初始化目錄,並建立一個例項

3、配置/etc/my.cnf,配置方法如下

[mysqld_multi]

mysqld = /usr/local/mysql/bin/mysqld_safe

mysqladmin = /usr/local/mysql/bin/mysqladmin

user = root

[mysqld] ## 本來mysql配置

server-id = 1

port = 3306

socket = /data/mysql/mysql.sock

datadir = /data/mysql

pid-file = /data/mysql/wzj.pid

log-error = /data/mysql/wzj.err

log-bin = /data/mysql/log/bin-log

log-bin-index = /data/mysql/log/mysql-bin.index

user = mysql

[mysqld2]  ##建立例項配置

server-id = 2

port = 3307

socket = /tmp/mysql2.sock

datadir = /data/mysql2/                         //mysql2儲存資料庫的地方,也就是例項

pid-file = /data/mysql2/mysql2.pid       //mysql2的pid檔案記錄

log-error = /data/mysql2/mysql2.err     //為錯誤日誌檔案的地方

user = mysql

#master-host =10.19.194.57

#master-user ='wzj_slave_test'

#master-pass ='Password@123456'

#master-port =3306

#master_connect_retry=60

#replicate-do-db =mysql_wzj

#replicate-ignore-db=mysql--------該段已註釋,因為新版本中,需要用CHANGE MASTER TO 命令去設定

【注意】:以上檔案的目錄,皆為系統建立,並非手動去建立,設定配置檔案後,重啟mysql,檔案就會自動建立

4、重啟,然後可以使用msyql_multi命令啟動例項,再檢視一下master主庫的狀態,其中Binlog_Do_DB表示要備份的資料庫,Binlog_Ignore_DB表示不備份的資料庫

shell>/etc/rc.d/init.d/mysqld start/stop/restart

shell>/usr/local/mysql/bin/mysqld_multi start 1-2  啟動例項 (1-2表示啟動1、2兩個例項)

shell>mysql master: mysql -P 3306 -u root -p -S /data/mysql/mysql.sock (密碼:1)

mysql>show master status; or show master status G;   顯示主庫的狀態,其中File 和Position 數值要記住,下面的mysql語句要用到,用於設定從庫

5、進入從庫,並設定從庫的一些引數

shell>slave:mysql -P 3307 -u root -p -S /tmp/mysql2.sock (密碼:回車)   ---另外開個遠端

mysql>CHANGE MASTER TO

mysql> MASTER_HOST='10.19.194.57',  ---主庫的地址

mysql>MASTER_USER='wzj_slave_test',  ---主庫使用者

mysql>MASTER_PASSWORD='Password@123456',   ---主庫的密碼

mysql>MASTER_LOG_FILE='bin-log.000013' ,  ---此引數為master status中的File值

mysql>MASTER_LOG_POS=120;   ---此數值為Position數值

6、設定好後,執行start slave,如果下圖紅線地方是YES,則成功,否則,檢視配置檔案是否有錯或有誤。

slave_io_running  :yes

slave_sql_running :yes

7、可以檢視從庫下mysql程序資訊

mysql>show processlist;

8、測試

在主庫上面建新的資料庫,然後在從庫中檢視是否有同步~

----------------------------------------------------------------------------------------------------

###1.2 開始實現###

思想我們已經講完了相信大家已經多多少少的理解了,但是我們要如何在phalapi去實現讀寫分離的操作

1.首先我們要在初始化一個數據庫連線,我們需要建立一個配置檔案read.php和dbs.php一樣只是連線這讀庫的配置項,並且註冊

//讀庫
DI()->read = function (){
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new PhalApi_DB_NotORM(DI()->config->get('read'), $debug);
};

2.對PhalApi_Model_NotORM檔案中的getORM進行修改

/**
 * 快速獲取ORM例項,注意每次獲取都是新的例項
 */
protected function getORM($id = NULL){
    $table = $this->getTableName($id);
    if($id == 'read'){
        return DI()->read->$table;
    }
    return DI()->notorm->$table;
}

3.當我們在model層使用**$this->getORM('read')** 的時候就會使用讀庫,使用**$this->getORM()** 會預設使用寫庫

//select操作
$this->getORM('read')->select('*')->where('aId', $aId)->fetchAll();
//insert,update,delete操作
$this->getORM()->insert();

##2. 多庫處理##

有些人會問,為什麼需要進行多庫處理,所有的表放到一個庫不久好了嗎?

在原來重構別人外包專案是遇到過一個庫100來張表,沒有備註沒有文件,幾乎沒法看,在我自己做一個比較大的專案的時候我也是做了一些考慮把庫根據業務分解成一個一個子庫,可以很好的避免表太多結構混亂的問題,而且我們可以隨時把任何一個子庫移植出去,當我一個mysql承載了很多壓力,我可以把這個mysql上面的子庫分解到多個mysql上面來實現壓力分流.

看了上面的這一段介紹相信大家不言而喻的瞭解了這樣做的好處,但是如何實現呢,聰明的大家可能在想不久和上面一樣在多註冊一個數據庫連線嘛,其實大家說對了一半,我們是需要註冊一個連線,但是我們需要一種統一的規範來使用這類操作

1.初始化資料庫連線,一樣的複製一份dbs.php為developers.php配置連線開發者庫

//開發者庫
DI()->developers = function (){
    $debug = !empty($_GET['__sql__']) ? true : false;
    return new PhalApi_DB_NotORM(DI()->config->get('developers'), $debug);
};

2.對PhalApi_Model_NotORM檔案中的getORM進行修改

/**
 * 快速獲取ORM例項,注意每次獲取都是新的例項
 */
protected function getORM($id = NULL){
    $table = $this->getTableName($id);
    if($id == 'developers'){
        return DI()->developers->$table;
    }
    return DI()->notorm->$table;
}

3.在之前我們不是建立了我們的公用General檔案我們在構建這樣的結構

--General                   //公用目錄
	--developers				//通用專案庫目錄
		--Domain				//專案庫Domain層
		--Model				//專案庫Model層

然後我們在這裡的Model進行的操作都是使用**$this->getORM('developers')**進行操作

這樣規範的好處就是在與共享模組化 讓正常的一個Model層不會使用到任何不同庫的操作,我們多個專案用到其他的一個庫可以進行程式碼複用,

##3. 總結##

其實實現今天介紹的兩種解決問題的方案還有很多很多,不同的業務可能需求不同實現也就不一樣希望今天的介紹對大家有幫助,後面兩篇教程將基於我寫的兩個拓展分別介紹分表分庫操作和redis實際的使用,希望大家進一步關注!

注:筆者能力有限有說的不對的地方希望大家能夠指出,也希望多多交流!

官網QQ交流群:421032344 歡迎大家的加入!