W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
先在這里感謝phalapi框架創(chuàng)始人@dogstar,為我們提供了這樣一個(gè)優(yōu)秀的開(kāi)源框架.
讀寫(xiě)分離是我們常用的一種解決方案,它可以解決大量讀操作的時(shí)候數(shù)據(jù)庫(kù)瓶頸的問(wèn)題,我們?cè)谡嬲_(kāi)發(fā)一個(gè)項(xiàng)目的過(guò)程中可能會(huì)遇一個(gè)接口或者一個(gè)操作中需要用到多個(gè)數(shù)據(jù)庫(kù)操作的時(shí)候怎么辦,今天的教程就從這個(gè)兩個(gè)問(wèn)題出來(lái),來(lái)聊聊使用phalapi怎么解決這個(gè)問(wèn)題.
附上:
喵了個(gè)咪的博客:w-blog.cn
官網(wǎng)地址:http://www.phalapi.net/
開(kāi)源中國(guó)Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release
在我們的生活中無(wú)時(shí)無(wú)刻不面臨著并發(fā)的問(wèn)題,比如下班高峰交通問(wèn)題,人們用了紅綠燈來(lái)解決的一部分問(wèn)題(但是很痛苦這個(gè)就和查詢的時(shí)候阻塞一樣的,10秒做update操作,10秒做select操作一樣的),那么人們有想到了一個(gè)方法高架,高架的路線是和正常的路線一致的(數(shù)據(jù)相同) ,高架分兩條路而且一條路上的車不能到另外一條路上(讀寫(xiě)分離) 這樣就解決了我們這類常規(guī)并發(fā)的問(wèn)題
其實(shí)看起來(lái)上面這種解決方案是比較好的其實(shí)并不是這樣的,有兩條路但是其實(shí)它的寬度是不一樣的,我們這里把一個(gè)叫做寫(xiě)路,一個(gè)叫做讀路,我們?nèi)绻鲆粋€(gè)讀路并且把他成倍的變寬是一件很簡(jiǎn)單的事情(也就是多從庫(kù)),但是我們要建立一條寫(xiě)路可以,但是我們要把這條寫(xiě)路變寬是比較困難的,我們一般不這樣做.
我是使用了阿里云的多讀庫(kù)服務(wù),這里引用一下百度經(jīng)驗(yàn)的mysql主從處理
----------------------------------------------------------------------------------------------------
MYSQL【一臺(tái)主機(jī)多個(gè)實(shí)例的主從配置】
1、建立賬號(hào)
進(jìn)入mysql數(shù)據(jù)庫(kù),創(chuàng)建一個(gè)用于從庫(kù)備份的賬號(hào)
mysql>GRANT REPLICATION SLAVE ON *.* TO 'slave_test'@'10.19.194.57' IDENTIFIED BY 'Password@123456';
mysql>FLUSH PRIVILEGES; ---刷新
該命令詳情參考grant創(chuàng)建用戶命令
2、如果已經(jīng)有一個(gè)實(shí)例在運(yùn)行(因?yàn)殚_(kāi)始已經(jīng)安裝了mysql,所以有一個(gè)默認(rèn)的),那么再啟動(dòng)一個(gè)實(shí)例,方法如下:
(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 這個(gè)為另外一個(gè)目錄,該步驟意味初始化目錄,并創(chuàng)建一個(gè)實(shí)例
3、配置/etc/my.cnf,配置方法如下
[mysqld_multi]
mysqld = /usr/local/mysql/bin/mysqld_safe
mysqladmin = /usr/local/mysql/bin/mysqladmin
user = root
[mysqld] ## 本來(lái)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] ##創(chuàng)建實(shí)例配置
server-id = 2
port = 3307
socket = /tmp/mysql2.sock
datadir = /data/mysql2/ //mysql2存儲(chǔ)數(shù)據(jù)庫(kù)的地方,也就是實(shí)例
pid-file = /data/mysql2/mysql2.pid //mysql2的pid文件記錄
log-error = /data/mysql2/mysql2.err //為錯(cuò)誤日志文件的地方
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--------該段已注釋,因?yàn)樾掳姹局?,需要用CHANGE MASTER TO 命令去設(shè)置
【注意】:以上文件的目錄,皆為系統(tǒng)創(chuàng)建,并非手動(dòng)去創(chuàng)建,設(shè)置配置文件后,重啟mysql,文件就會(huì)自動(dòng)創(chuàng)建
4、重啟,然后可以使用msyql_multi命令啟動(dòng)實(shí)例,再查看一下master主庫(kù)的狀態(tài),其中Binlog_Do_DB表示要備份的數(shù)據(jù)庫(kù),Binlog_Ignore_DB表示不備份的數(shù)據(jù)庫(kù)
shell>/etc/rc.d/init.d/mysqld start/stop/restart
shell>/usr/local/mysql/bin/mysqld_multi start 1-2 啟動(dòng)實(shí)例 (1-2表示啟動(dòng)1、2兩個(gè)實(shí)例)
shell>mysql master: mysql -P 3306 -u root -p -S /data/mysql/mysql.sock (密碼:1)
mysql>show master status; or show master status \G; 顯示主庫(kù)的狀態(tài),其中File 和Position 數(shù)值要記住,下面的mysql語(yǔ)句要用到,用于設(shè)置從庫(kù)
5、進(jìn)入從庫(kù),并設(shè)置從庫(kù)的一些參數(shù)
shell>slave:mysql -P 3307 -u root -p -S /tmp/mysql2.sock (密碼:回車) ---另外開(kāi)個(gè)遠(yuǎn)程
mysql>CHANGE MASTER TO
mysql> MASTER_HOST='10.19.194.57', ---主庫(kù)的地址
mysql>MASTER_USER='wzj_slave_test', ---主庫(kù)用戶
mysql>MASTER_PASSWORD='Password@123456', ---主庫(kù)的密碼
mysql>MASTER_LOG_FILE='bin-log.000013' , ---此參數(shù)為master status中的File值
mysql>MASTER_LOG_POS=120; ---此數(shù)值為Position數(shù)值
6、設(shè)置好后,運(yùn)行start slave,如果下圖紅線地方是YES,則成功,否則,查看配置文件是否有錯(cuò)或有誤。
slave_io_running :yes
slave_sql_running :yes
7、可以查看從庫(kù)下mysql進(jìn)程信息
mysql>show processlist;
8、測(cè)試
在主庫(kù)上面建新的數(shù)據(jù)庫(kù),然后在從庫(kù)中查看是否有同步~
----------------------------------------------------------------------------------------------------
思想我們已經(jīng)講完了相信大家已經(jīng)多多少少的理解了,但是我們要如何在phalapi去實(shí)現(xiàn)讀寫(xiě)分離的操作
1.首先我們要在初始化一個(gè)數(shù)據(jù)庫(kù)連接,我們需要建立一個(gè)配置文件read.php和dbs.php一樣只是連接這讀庫(kù)的配置項(xiàng),并且注冊(cè)
//讀庫(kù)
DI()->read = function (){
$debug = !empty($_GET['__sql__']) ? true : false;
return new PhalApi_DB_NotORM(DI()->config->get('read'), $debug);
};
2.對(duì)PhalApi_Model_NotORM文件中的getORM進(jìn)行修改
/**
* 快速獲取ORM實(shí)例,注意每次獲取都是新的實(shí)例
*/
protected function getORM($id = NULL){
$table = $this->getTableName($id);
if($id == 'read'){
return DI()->read->$table;
}
return DI()->notorm->$table;
}
3.當(dāng)我們?cè)趍odel層使用$this->getORM('read') 的時(shí)候就會(huì)使用讀庫(kù),使用$this->getORM() 會(huì)默認(rèn)使用寫(xiě)庫(kù)
//select操作
$this->getORM('read')->select('*')->where('aId', $aId)->fetchAll();
//insert,update,delete操作
$this->getORM()->insert();
有些人會(huì)問(wèn),為什么需要進(jìn)行多庫(kù)處理,所有的表放到一個(gè)庫(kù)不就好了嗎?
在原來(lái)重構(gòu)別人外包項(xiàng)目是遇到過(guò)一個(gè)庫(kù)100來(lái)張表,沒(méi)有備注沒(méi)有文檔,幾乎沒(méi)法看,在我自己做一個(gè)比較大的項(xiàng)目的時(shí)候我也是做了一些考慮把庫(kù)根據(jù)業(yè)務(wù)分解成一個(gè)一個(gè)子庫(kù),可以很好的避免表太多結(jié)構(gòu)混亂的問(wèn)題,而且我們可以隨時(shí)把任何一個(gè)子庫(kù)移植出去,當(dāng)我一個(gè)mysql承載了很多壓力,我可以把這個(gè)mysql上面的子庫(kù)分解到多個(gè)mysql上面來(lái)實(shí)現(xiàn)壓力分流.
看了上面的這一段介紹相信大家不言而喻的了解了這樣做的好處,但是如何實(shí)現(xiàn)呢,聰明的大家可能在想不久和上面一樣在多注冊(cè)一個(gè)數(shù)據(jù)庫(kù)連接嘛,其實(shí)大家說(shuō)對(duì)了一半,我們是需要注冊(cè)一個(gè)連接,但是我們需要一種統(tǒng)一的規(guī)范來(lái)使用這類操作
1.初始化數(shù)據(jù)庫(kù)連接,一樣的復(fù)制一份dbs.php為developers.php配置連接開(kāi)發(fā)者庫(kù)
//開(kāi)發(fā)者庫(kù)
DI()->developers = function (){
$debug = !empty($_GET['__sql__']) ? true : false;
return new PhalApi_DB_NotORM(DI()->config->get('developers'), $debug);
};
2.對(duì)PhalApi_Model_NotORM文件中的getORM進(jìn)行修改
/**
* 快速獲取ORM實(shí)例,注意每次獲取都是新的實(shí)例
*/
protected function getORM($id = NULL){
$table = $this->getTableName($id);
if($id == 'developers'){
return DI()->developers->$table;
}
return DI()->notorm->$table;
}
3.在之前我們不是建立了我們的公用General文件我們?cè)跇?gòu)建這樣的結(jié)構(gòu)
--General //公用目錄
--developers //通用項(xiàng)目庫(kù)目錄
--Domain //項(xiàng)目庫(kù)Domain層
--Model //項(xiàng)目庫(kù)Model層
然后我們?cè)谶@里的Model進(jìn)行的操作都是使用$this->getORM('developers')進(jìn)行操作
這樣規(guī)范的好處就是在與共享和模塊化 讓正常的一個(gè)Model層不會(huì)使用到任何不同庫(kù)的操作,我們多個(gè)項(xiàng)目用到其他的一個(gè)庫(kù)可以進(jìn)行代碼復(fù)用,
其實(shí)實(shí)現(xiàn)今天介紹的兩種解決問(wèn)題的方案還有很多很多,不同的業(yè)務(wù)可能需求不同實(shí)現(xiàn)也就不一樣希望今天的介紹對(duì)大家有幫助,后面兩篇教程將基于我寫(xiě)的兩個(gè)拓展分別介紹分表分庫(kù)操作和redis實(shí)際的使用,希望大家進(jìn)一步關(guān)注!
注:筆者能力有限有說(shuō)的不對(duì)的地方希望大家能夠指出,也希望多多交流!
官網(wǎng)QQ交流群:421032344 歡迎大家的加入!
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: