新聞中心
怎樣用php實現(xiàn)兩個mysql數(shù)據(jù)庫的同步
使用程序無法實現(xiàn)這種功能,因為無法保證事務(wù)的一致性,比如:A數(shù)據(jù)庫中的a表復(fù)制到B數(shù)據(jù)庫中的a表的過程中,A數(shù)據(jù)庫中的a表的一條記錄被刪除,這樣就無法實現(xiàn)數(shù)據(jù)的一致性!正確的做法是使用MySQL復(fù)制的功能!很簡單,只需要幾步配置即可!
站在用戶的角度思考問題,與客戶深入溝通,找到輝縣網(wǎng)站設(shè)計與輝縣網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:網(wǎng)站建設(shè)、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名申請、網(wǎng)頁空間、企業(yè)郵箱。業(yè)務(wù)覆蓋輝縣地區(qū)。
php redis做mysql的緩存,怎么異步redis同步到mysql數(shù)據(jù)庫
對于變化頻率非常快的數(shù)據(jù)來說,如果還選擇傳統(tǒng)的靜態(tài)緩存方式(Memocached、File System等)展示數(shù)據(jù),可能在緩存的存取上會有很大的開銷,并不能很好的滿足需要,而Redis這樣基于內(nèi)存的NoSQL數(shù)據(jù)庫,就非常適合擔(dān)任實時數(shù)據(jù)的容器。
但是往往又有數(shù)據(jù)可靠性的需求,采用MySQL作為數(shù)據(jù)存儲,不會因為內(nèi)存問題而引起數(shù)據(jù)丟失,同時也可以利用關(guān)系數(shù)據(jù)庫的特性實現(xiàn)很多功能。
所以就會很自然的想到是否可以采用MySQL作為數(shù)據(jù)存儲引擎,Redis則作為Cache。而這種需求目前還沒有看到有特別成熟的解決方案或工具,因此采用Gearman+PHP+MySQL UDF的組合異步實現(xiàn)MySQL到Redis的數(shù)據(jù)復(fù)制。
MySQL到Redis數(shù)據(jù)復(fù)制方案
無論MySQL還是Redis,自身都帶有數(shù)據(jù)同步的機制,比較常用的MySQL的Master/Slave模式,就是由Slave端分析Master的binlog來實現(xiàn)的,這樣的數(shù)據(jù)復(fù)制其實還是一個異步過程,只不過當(dāng)服務(wù)器都在同一內(nèi)網(wǎng)時,異步的延遲幾乎可以忽略。
那么理論上也可以用同樣方式,分析MySQL的binlog文件并將數(shù)據(jù)插入Redis。但是這需要對binlog文件以及MySQL有非常深入的理解,同時由于binlog存在Statement/Row/Mixedlevel多種形式,分析binlog實現(xiàn)同步的工作量是非常大的。
因此這里選擇了一種開發(fā)成本更加低廉的方式,借用已經(jīng)比較成熟的MySQL UDF,將MySQL數(shù)據(jù)首先放入Gearman中,然后通過一個自己編寫的PHP Gearman Worker,將數(shù)據(jù)同步到Redis。比分析binlog的方式增加了不少流程,但是實現(xiàn)成本更低,更容易操作。
Gearman的安裝與使用
Gearman是一個支持分布式的任務(wù)分發(fā)框架。設(shè)計簡潔,獲得了非常廣泛的支持。一個典型的Gearman應(yīng)用包括以下這些部分:
Gearman Job Server:Gearman核心程序,需要編譯安裝并以守護(hù)進(jìn)程形式運行在后臺
Gearman Client:可以理解為任務(wù)的收件員,比如在后臺執(zhí)行一個發(fā)送郵件的任務(wù),可以在程序中調(diào)用一個Gearman Client并傳入郵件的信息,然后就可以將執(zhí)行結(jié)果立即展示給用戶,而任務(wù)本身會慢慢在后臺運行。
Gearman Worker:任務(wù)的真正執(zhí)行者,一般需要自己編寫具體邏輯并通過守護(hù)進(jìn)程方式運行,Gearman Worker接收到Gearman Client傳遞的任務(wù)內(nèi)容后,會按順序處理。
以前曾經(jīng)介紹過類似的后臺任務(wù)處理項目Resque。兩者的設(shè)計其實非常接近,簡單可以類比為:
Gearman Job Server:對應(yīng)Resque的Redis部分
Gearman Client:對應(yīng)Resque的Queue操作
Gearman Worker:對應(yīng)Resque的Worker和Job
這里之所以選擇Gearman而不是Resque是因為Gearman提供了比較好用的MySQL UDF,工作量更小。
安裝Gearman及PHP Gearman擴展
以下均以Ubuntu12.04為例。
apt-get install gearman gearman-server libgearman-dev
檢查Gearman的運行狀況:
/etc/init.d/gearman-job-server status
* gearmand is running
說明Gearman已經(jīng)安裝成功。
PHP的Gearman擴展可以通過pecl直接安裝
pecl install gearman
echo "extension=gearman.so"/etc/php5/conf.d/gearman.ini
service php5-fpm restart
但是實測發(fā)現(xiàn)ubuntu默認(rèn)安裝的gearman版本過低,直接運行pecl install gearman會報錯
configure: error: libgearman version 1.1.0or later required
因此Gearman + PHP擴展建議通過編譯方式安裝,這里為了簡單說明,選擇安裝舊版本擴展:
pecl install gearman-1.0.3
Gearman + PHP實例
為了更容易理解后文Gearman的運行流程,這里不妨從一個最簡單的Gearman實例來說明,比如要進(jìn)行一個文件處理的操作,首先編寫一個Gearman Client并命名為client.php:
?php
$client =newGearmanClient();
$client-addServer();
$client-doBackground('writeLog','Log content');
echo '文件已經(jīng)在后臺操作';
運行這個文件,相當(dāng)于模擬用戶請求一個Web頁面后,將處理結(jié)束的信息返回用戶:
php client.php
查看一下Gearman的狀況:
(echo status ; sleep 0.1)| netcat127.0.0.14730
可以看到輸出為
writeLog ? ? ? ?100.
說明已經(jīng)在Gearman中建立了一個名為writeLog的任務(wù),并且有1個任務(wù)在隊列等待中。
而上面的4列分別代表當(dāng)前的Gearman的運行狀態(tài):
任務(wù)名稱
在等待隊列中的任務(wù)
正在運行的任務(wù)
正在運行的Worker進(jìn)程
可以使用watch進(jìn)行實時監(jiān)控:
watch -n 1"(echo status; sleep 0.1) | nc 127.0.0.1 4730"
然后我們需要編寫一個Gearman Worker命名為worker.php:
?php
$worker =newGearmanWorker();
$worker-addServer();
$worker-addFunction('writeLog','writeLog');while($worker-work());function writeLog($job){
$log = $job-workload();file_put_contents(__DIR__ .'/gearman.log', $log ."\n", FILE_APPEND | LOCK_EX);}
Worker使用一個while死循環(huán)實現(xiàn)守護(hù)進(jìn)程,運行
php worker.php
可以看到Gearman狀態(tài)變?yōu)椋?/p>
writeLog ? ? ? ?001
同時查看同目錄下gearman.log,內(nèi)容應(yīng)為從Client傳入的值Log content。
通過MySQL UDF + Trigger同步數(shù)據(jù)到Gearman
MySQL要實現(xiàn)與外部程序互通的最好方式還是通過MySQL UDF(MySQL user defined functions)來實現(xiàn)。為了讓MySQL能將數(shù)據(jù)傳入Gearman,這里使用了lib_mysqludf_json和gearman-mysql-udf的組合。
安裝lib_mysqludf_json
使用lib_mysqludf_json的原因是因為Gearman只接受字符串作為入口參數(shù),可以通過lib_mysqludf_json將MySQL中的數(shù)據(jù)編碼為JSON字符串
apt-get install libmysqlclient-dev
wget
unzip master.zip
cd lib_mysqludf_json-master/
rm lib_mysqludf_json.so
gcc $(mysql_config --cflags)-shared -fPIC -o lib_mysqludf_json.so lib_mysqludf_json.c
可以看到重新編譯生成了 lib_mysqludf_json.so 文件,此時需要查看MySQL的插件安裝路徑:
mysql -u root -pPASSWORD --execute="show variables like '%plugin%';"+---------------+------------------------+|Variable_name|Value|+---------------+------------------------+| plugin_dir ? ?|/usr/lib/mysql/plugin/|+---------------+------------------------+
然后將 lib_mysqludf_json.so 文件復(fù)制到對應(yīng)位置:
cp lib_mysqludf_json.so /usr/lib/mysql/plugin/
最后登入MySQL運行語句注冊UDF函數(shù):
CREATE FUNCTION json_object RETURNS STRING SONAME 'lib_mysqludf_json.so';
安裝gearman-mysql-udf
方法幾乎一樣:
apt-get install libgearman-dev
wget
tar -xzf gearman-mysql-udf-0.6.tar.gz
cd gearman-mysql-udf-0.6./configure --with-mysql=/usr/bin/mysql_config
-libdir=/usr/lib/mysql/plugin/
make make install
登入MySQL運行語句注冊UDF函數(shù):
CREATE FUNCTION gman_do_background RETURNS STRING SONAME 'libgearman_mysql_udf.so';
CREATE FUNCTION gman_servers_set RETURNS STRING SONAME 'libgearman_mysql_udf.so';
最后指定Gearman服務(wù)器的信息:
SELECT gman_servers_set('127.0.0.1:4730');
通過MySQL觸發(fā)器實現(xiàn)數(shù)據(jù)同步
最終同步哪些數(shù)據(jù),同步的條件,還是需要根據(jù)實際情況決定,比如將數(shù)據(jù)表data的數(shù)據(jù)在每次更新時同步,那么編寫Trigger如下:
DELIMITER $$
CREATE TRIGGER datatoredis AFTER UPDATE ON data
FOR EACH ROW BEGIN
SET @ret=gman_do_background('syncToRedis', json_object(NEW.id as`id`, NEW.volume as`volume`));END$$
DELIMITER ;
嘗試在數(shù)據(jù)庫中更新一條數(shù)據(jù)查看Gearman是否生效。
Gearman PHP Worker將MySQL數(shù)據(jù)異步復(fù)制到Redis
Redis作為時下當(dāng)熱的NoSQL緩存解決方案無需過多介紹,其安裝及使用也非常簡單:
apt-get install redis-server
pecl install redis
echo "extension=redis.so"/etc/php5/conf.d/redis.ini
然后編寫一個Gearman Worker:redis_worker.php
#!/usr/bin/env php?
$worker =newGearmanWorker();
$worker-addServer();
$worker-addFunction('syncToRedis','syncToRedis');
$redis =newRedis();
$redis-connect('127.0.0.1',6379);while($worker-work());function syncToRedis($job){global $redis;
$workString = $job-workload();
$work = json_decode($workString);if(!isset($work-id)){returnfalse;}
$redis-set($work-id, $workString);}
最后需要將Worker在后臺運行:
nohup php redis_worker.php
通過這種方式將MySQL數(shù)據(jù)復(fù)制到Redis,經(jīng)測試單Worker基本可以瞬時完成。
同一個服務(wù)器上兩個數(shù)據(jù)庫表怎么同步
如果是同一個mysql服務(wù)端的兩個數(shù)據(jù)庫同步可考慮下觸發(fā)器,如果是不同端口的兩個mysql服務(wù)端跟在兩臺服務(wù)器同步配置上沒有區(qū)別。
數(shù)據(jù)庫最好不要做主從,不然性能會降低很多的。
可以采取其他的方法撒,比如分布式存儲。可以考慮下memcachedb,實現(xiàn)持久存儲。
表結(jié)構(gòu)一致的話,可以考慮映射表去實現(xiàn)來的(shell腳本定時同步,觸發(fā)器),不過shell腳本會將環(huán)境搞的復(fù)雜一點,維護(hù)也會相對麻煩.映射表具體實現(xiàn)(在要同步的數(shù)據(jù)庫下創(chuàng)建相同的表結(jié)構(gòu)):
1
2
3
4
5
6
7
8
CREATE TABLE table_name
(
column_name column_type ....
....
key ....
)
ENGINE=MYISAM DEFAULT CHARSET=utf8
CONNECTION="mysql://user:pwd@ip_address/db_name/table_name";
php+mysql 數(shù)據(jù)庫表里怎么取需要的數(shù)據(jù)
先配置數(shù)據(jù)庫------連接數(shù)據(jù)庫--------選擇數(shù)據(jù)庫--------填寫檢索表-------輸出檢索內(nèi)容
第一種解決方法:
一、配置一下數(shù)據(jù)庫:
define("DB_HOST","localhost");//數(shù)據(jù)庫地址,一般為localhost
define("DB_USER","root");//數(shù)據(jù)庫用戶名
define("DB_PSW","");//數(shù)據(jù)庫密碼
define("DB_DB","databasename");//需要操作的數(shù)據(jù)庫
二、連接數(shù)據(jù)庫:
$conn = mysql_connect(DB_HOST,DB_USER,DB_PSW) or die
三、選擇數(shù)據(jù)庫:
mysql_select_db(DB_DB,$conn) or die
四、檢索表:(填寫tablename)
$result = mysql_query("select * from tablename") or die
五、輸出檢索的內(nèi)容:
while ($row = mysql_fetch_row($result)){foreach($row as $data){ echo $data.' ';} echo 'br。
如何用php實現(xiàn)兩個Oracle數(shù)據(jù)庫同步功能?
你是希望用PHP代碼實現(xiàn)同時寫兩個數(shù)據(jù)庫還是希望只是兩個數(shù)據(jù)庫的數(shù)據(jù)一致?如果僅是希望數(shù)據(jù)庫數(shù)據(jù)數(shù)據(jù)一至,oracle自帶的機制就能實現(xiàn)。如果是想自己編程實現(xiàn)同時兩個數(shù)據(jù)庫的操作,也方便,PHP在鏈接不同數(shù)據(jù)庫實例時,會得到不同的鏈接句柄,在后面具體操作時,同時對這兩個鏈接句柄操作就行了,但這樣存在數(shù)據(jù)不完全一致的風(fēng)險,必須校驗,這樣又拖慢了速度。
演示代碼如下:
echo "br /b演示多數(shù)據(jù)庫克隆操作(多數(shù)據(jù)庫同時寫操作)/bbr /";
$this-loadModel('student.php',1);
//如果兩個不同數(shù)據(jù)庫服務(wù)器的表對象結(jié)構(gòu)完全一致,則不必重復(fù)載入表對象定義文件,只需要在實例化時指定服務(wù)器id就行了。
//$this-loadModel('student.php',2);
$this-loadModel('student2.php',2);
$student1=new Tstudent(1);
$student2=new Tstudent2(2);
$student3=new Tstudent(2);
$student2-cloneFrom($student1);
$student3-cloneFrom($student1);
$student1-uuid='999';
$student1-id='999';
$student1-name='測試克隆人';
//如果進(jìn)行了主對象的克隆操作,則在完成主對象數(shù)據(jù)持久化后,所有的子對象將會同步插入數(shù)據(jù)。
$student1-insert();
用php同步A數(shù)據(jù)庫中的a表 的數(shù)據(jù)到 數(shù)據(jù)庫B中的b表,要如何實現(xiàn)呢
首先要把數(shù)據(jù)庫A、B的連接權(quán)限都grant給一個用戶,然后用這個用戶連接數(shù)據(jù)庫。
那么可以用A.a, B.b這樣去訪問表。
剩下的就是SQL select ... insert into語句的事,相信你會。
分享標(biāo)題:php數(shù)據(jù)庫表同步,php讀寫分離數(shù)據(jù)庫同步
本文鏈接:http://www.ef60e0e.cn/article/dsidpds.html