在許多大型專案中讀寫分離是常用的解決方案,它可以解決大量讀取操作的時候資料庫瓶頸的問題。那麼如何去建構讀寫分離的資料庫分佈,以及程式端如何進行讀寫分離操作呢?本文就基於phalapi從實例講解讀寫分離的實作,希望對大家有幫助。
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层不会使用到任何不同库的操作,我们多个项目用到其他的一个库可以进行代码复用,
相关推荐:
以上是phalapi之如何實現資料庫讀寫分離的詳細內容。更多資訊請關注PHP中文網其他相關文章!