#phalapi-進階篇5(數據庫讀寫分離以及多庫使用)#php
##前言## 先在這裏感謝phalapi框架創始人@dogstar,爲咱們提供了這樣一個優秀的開源框架.mysql
讀寫分離是咱們經常使用的一種解決方案,它能夠解決大量讀操做的時候數據庫瓶頸的問題,咱們在真正開發一個項目的過程當中可能會遇一個接口或者一個操做中須要用到多個數據庫操做的時候怎麼辦,今天的教程就從這個兩個問題出來,來聊聊使用phalapi怎麼解決這個問題.git
附上:redis
官網地址:http://www.phalapi.net/sql
開源中國Git地址:http://git.oschina.net/dogstar/PhalApi/tree/releaseshell
##1. 讀寫分離##數據庫
在咱們的生活中無時無刻不面臨這併發的問題,好比下班高峯交通問題,人們用了紅綠燈來解決的一部分問題**(可是很痛苦這個就和查詢的時候阻塞同樣的,10秒作update操做,10秒作select操做同樣的),那麼人們有想到了一個方法高架,高架的路線是和正常的路線一致的(數據相同)** ,高架分兩條路並且一條路上的車不能到另一條路上**(讀寫分離)** 這樣就解決了咱們這類常規併發的問題api
其實看起來上面這種解決方案是比較好的其實並非這樣的,有兩條路可是其實它的寬度是不同的,咱們這裏把一個叫作寫路,一個叫作讀路,咱們若是要作一個讀路而且把他成倍的變寬是一件很簡單的事情(也就是多從庫),可是咱們要創建一條寫路能夠,可是咱們要把這條寫路變寬是比較困難的,咱們通常不這樣作.併發
###1.1 mysql主從配置###框架
我是使用了阿里雲的多讀庫服務,這裏引用一下百度經驗的mysql主從處理
----------------------------------------------------------------------------------------------------
MYSQL【一臺主機多個實例的主從配置】
一、創建帳號
進入mysql數據庫,建立一個用於從庫備份的帳號
mysql>GRANT REPLICATION SLAVE ON *.* TO 'slave_test'@'10.19.194.57' IDENTIFIED BY 'Password@123456'; mysql>FLUSH PRIVILEGES; ---刷新
該命令詳情參考grant建立用戶命令
二、若是已經有一個實例在運行(由於開始已經安裝了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 這個爲另一個目錄,該步驟意味初始化目錄,並建立一個實例
三、配置/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,文件就會自動建立
四、重啓,而後可使用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表示啓動一、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語句要用到,用於設置從庫
五、進入從庫,並設置從庫的一些參數
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數值
六、設置好後,運行start slave,若是下圖紅線地方是YES,則成功,不然,查看配置文件是否有錯或有誤。
slave_io_running :yes slave_sql_running :yes
七、能夠查看從庫下mysql進程信息
mysql>show processlist;
八、測試
在主庫上面建新的數據庫,而後在從庫中查看是否有同步~
----------------------------------------------------------------------------------------------------
###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 歡迎你們的加入!