資料庫程序間通訊解決方案之MQ
資料庫程序間通訊解決方案之MQ
摘要
你是否想過當資料庫中的資料發生變化的時候出發某種操作?但因資料無法與其他程序通訊(傳遞訊號)讓你放棄,而改用每隔一段時間查詢一次資料變化的方法?下面的外掛可以解決你的問題。
原文出處:http://netkiller.github.io/journal/mysql.plugin.fifo.html
目錄
- 1. 背景
- 2. 應用場景
- 3. Mysql plugin
- 4. plugin 的開發與使用
- 5. 外掛如何使用
1. 背景
之前我發表過一篇文章 http://netkiller.github.io/journal/mysql.plugin.fifo.html
該文章中提出了通過fifo 管道,實現資料庫與其他程序的通訊。屬於 IPC 機制(同一個OS/伺服器內),後我有采用ZeroMQ重新實現了一個 RPC 機制的方案,同時相容IPC(跨越OS/伺服器)
各種縮寫的全稱 IPC(IPC :Inter-Process Communication 程序間通訊),ITC(ITC : Inter Thread Communication 執行緒間通訊)與RPC(RPC: Remote Procedure Calls遠端過程呼叫)。
支援協議
inproc://my_publisher
tcp://server001:5555
ipc:///tmp/feeds/0
2. 應用場景
如果你像處理資料,由於各種原因你不能在程式中實現,你可以使用這個外掛。當資料庫中的資料發生變化的時候出發某種操作,你可以使用這個外掛。
有時候你的專案可能是外包的,專案結束後外包方不會在管你,你有無法改動現有程式碼,或者根本不敢改。你可以使用這個外掛
採用MQ技術對資料庫無任何壓力,與採用程式處理並無不同,省卻了寫程式碼
處理方法,可以採用同步或者非同步方式
例 1. 傳送簡訊
傳送簡訊、郵件,只需要查詢出相應手機號碼,傳送到MQ的服務端,服務端接收到手機號碼後,放入佇列中,多執行緒程式從佇列中領取任務,傳送簡訊。
select zmq_client('tcp://localhost:5555',mobile) from demo where subscribed='Y' ...;
傳遞多個引數,可以使用符號分隔
select zmq_client('tcp://localhost:5555',concat(name,',',mobile,', news')) from demo; select zmq_client('tcp://localhost:5555',concat(name,'|',mobile,'|news')) from demo;
json格式
select zmq_client('tcp://localhost:5555',concat('{name:',name,', tel:',mobile,', template:news}')) from demo;
建議採用非同步方式,MQ端接收到任務立即反饋 “成功”資訊,因為我們不太關心是否能傳送成功,本身就是盲目性的傳送,手機號碼是否可用我們無從得知,簡訊或者郵件的傳送到達率不是100%,所以當進入佇列後,讓程式自行處理,將成功或者失敗資訊記錄到日誌中即可。
例 2. 處理圖片
首先查詢出需要處理圖片,然後將路徑與解析度傳遞給MQ另一端的處理程式
select zmq_client('tcp://localhost:5555',concat(image,',800x600}')) from demo;
建議採用非同步方式,MQ端接收到任務立即反饋 “成功”資訊
例 3. 身份證號碼校驗
select zmq_client('tcp://localhost:5555',id_number) from demo;
可以採用同步方案,因為MQ款處理幾乎不會延遲,直接將處理結構反饋
例 4. 靜態化案例
情景模擬,你的專案是你個電商專案,採用外包模式開發,專案已經開發完成。外包放不再負責維護,你現在要做靜態化。增加該功能,你要檢查多處與商品表相關的造作。
於其改程式碼,不如程式從外部處理,這樣更保險。我們只要寫一個程式將動態 URL 下載儲存成靜態即可,當資料發生變化的時候重新下載覆蓋即可
CREATE DEFINER=`dba`@`%` TRIGGER `demo_after_insert` AFTER INSERT ON `demo` FOR EACH ROW BEGIN
select zmq_client('tcp://localhost:5555', NEW.id);
END
CREATE DEFINER=`dba`@`%` TRIGGER `demo_after_update` AFTER UPDATE ON `demo` FOR EACH ROW BEGIN
select zmq_client('tcp://localhost:5555', NEW.id);
END
CREATE DEFINER=`dba`@`%` TRIGGER `demo_after_delete` AFTER DELETE ON `demo` FOR EACH ROW BEGIN
select zmq_client('tcp://localhost:5555', NEW.id);
END
MQ 另一端的服務會下載http://www.example.com/goods.php?cid=111&id=100, 然後生成html頁面,http://www.example.com/111/100.html
插入會新建頁面,更新會覆蓋頁面,刪除會刪除頁面
這樣無論商品的價格,屬性改變,靜態化程式都會做出相應的處理。
例 5. 資料同步案例
我們有多個數據庫,A 庫裡面的資料發生變化後,要同步書庫到B庫,或者處理結果,或者資料轉換後寫入其他資料庫中
方法也是採用觸發器或者EVENT處理
3. Mysql plugin
我開發了幾個 UDF, 共4個 function
UDF
- zmq_client(sockt,message)
- sockt .成功返回true,失敗返回flase.
有了上面的function後你就可以在begin,commit,rollback 直接穿插使用,實現在事物處理期間做你愛做的事。也可以用在觸發器與EVENT定時任務中。
4. plugin 的開發與使用
編譯UDF你需要安裝下面的軟體包
sudo apt-get install pkg-config
sudo apt-get install libmysqlclient-dev
sudo apt-get install gcc gcc-c++ make cmake
https://github.com/netkiller/mysql-zmq-plugin
編譯udf,最後將so檔案複製到 /usr/lib/mysql/plugin/
git clone https://github.com/netkiller/mysql-zmq-plugin.git
cd mysql-zmq-plugin
cmake .
make && make install
裝載
create function zmq_client returns string soname 'libzeromq.so';
create function zmq_publish returns string soname 'libzeromq.so';
解除安裝
drop function zmq_client;
drop function zmq_publish;
確認安裝成功
mysql> SELECT * FROM `mysql`.`func` where name like 'zmq%';
+-------------+-----+--------------+----------+
| name | ret | dl | type |
+-------------+-----+--------------+----------+
| zmq_client | 0 | libzeromq.so | function |
| zmq_publish | 0 | libzeromq.so | function |
+-------------+-----+--------------+----------+
2 rows in set (0.00 sec)
5. 外掛如何使用
外掛有很多種用法,這裡僅僅一個例
編譯zeromq server 測試程式
cd test
cmake .
make
啟動服務程序
./server
傳送Hello world!
mysql> select zmq_client('tcp://localhost:5555','Hello world!');
+---------------------------------------------------+
| zmq_client('tcp://localhost:5555','Hello world!') |
+---------------------------------------------------+
| Hello world! OK |
+---------------------------------------------------+
1 row in set (0.01 sec)
檢視伺服器端是否接收到資訊。
$ ./server
Received: Hello world!
我們再將上面的例子使用觸發器進一步優化
mysql> select zmq_client('tcp://localhost:5555',mobile) from demo;
+-------------------------------------------+
| zmq_client('tcp://localhost:5555',mobile) |
+-------------------------------------------+
| 13113668891 OK |
| 13113668892 OK |
| 13113668893 OK |
| 13322993040 OK |
| 13588997745 OK |
+-------------------------------------------+
5 rows in set (0.03 sec)
伺服器端已經接收到資料庫發過來的資訊
$ ./server
Received: Hello world!
Received: 13113668891
Received: 13113668892
Received: 13113668893
Received: 13322993040
Received: 13588997745
我們可以拼裝json或者序列化資料,傳送給遠端
mysql> select zmq_client('tcp://localhost:5555',concat('{name:',name,', tel:',mobile,'}')) from demo;
+------------------------------------------------------------------------------+
| zmq_client('tcp://localhost:5555',concat('{name:',name,', tel:',mobile,'}')) |
+------------------------------------------------------------------------------+
| {name:neo, tel:13113668891} OK |
| {name:jam, tel:13113668892} OK |
| {name:leo, tel:13113668893} OK |
| {name:jerry, tel:13322993040} OK |
| {name:tom, tel:13588997745} OK |
+------------------------------------------------------------------------------+
5 rows in set (0.03 sec)
返回資料取決於你服務端怎麼編寫處理程式,你可以返回true/false等等。
觸發器以及事務處理,這裡就不演示了