开发者社区> 问答> 正文

数据库进程间通信解决方案 数据库进程间通信解决方案 :报错

数据库进程间通信解决方案 数据库进程间通信解决方案 1. 背景 2. 解决思路 3. Mysql plugin 4. plugin 的开发与使用 5. 插件如何使用 6. 部署相关问题

数据库进程间通信解决方案

数据库与其他第三方应用程序进程间通信解决方案

<h3> Mr. Neo Chen (netkiller), 陈景峰(BG7NYT) </h3> 

中国广东省深圳市龙华新区民治街道溪山美地 518131 +86 13113668890 +86 755 29812080 <netkiller@msn.com>

$Id: mysql-plugin.xml 587 2013-12-16 14:00:00Z netkiller $  


版权 © 2011, 2012, 2013, 2014 http://netkiller.github.io  



 <strong>版权声明</strong>  
 转载请与作者联系,转载时请务必标明文章原始出处和作者信息及本声明。  
<table style="border:0px;"> 
 <tbody> 
  <tr> 
   <td> <a href="http://creativecommons.org/licenses/by/3.0/" target="_top" rel="nofollow"> 
     <table style="border:0px;width:180px;"> 
      <tbody> 
       <tr> 
        <td> <img src="http://static.oschina.net/uploads/img/201405/19110303_lWwI.png" width="180" /> </td> 
       </tr> 
      </tbody> 
     </table> </a> </td> 
   <td> 
    <table style="border:0px;"> 
     <tbody> 
      <tr> 
       <td> 文档出处: </td> 
      </tr> 
      <tr> 
       <td> <a href="http://netkiller.github.io/" target="_top" rel="nofollow">http://netkiller.github.io</a> </td> 
      </tr> 
      <tr> 
       <td> <a href="http://netkiller.sourceforge.net/" target="_top" rel="nofollow">http://netkiller.sourceforge.net</a> </td> 
      </tr> 
     </tbody> 
    </table> </td> 
  </tr> 
 </tbody> 
</table> 



$Date: 2013-12-16 13:34:20 +0800 (Thu, 16 May 2013) $  




  摘要 
 
 你是否想过当数据库中的数据发生变化的时候出发某种操作?但因数据无法与其他进程通信(传递信号)让你放弃,而改用每隔一段时间查询一次数据变化的方法?下面的插件可以解决你的问题。  
 原文出处:<a href="http://netkiller.github.io/journal/mysql.plugin.fifo.html" target="_top" rel="nofollow">http://netkiller.github.io/journal/mysql.plugin.fifo.html</a>  





  我的系列文档 
 
<table style="border:0px;"> 
 <tbody> 
  <tr> 
   <td> <a href="http://netkiller.github.io/architect/index.html" target="_top" rel="nofollow">Netkiller Architect 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/developer/index.html" target="_top" rel="nofollow">Netkiller Developer 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/php/index.html" target="_top" rel="nofollow">Netkiller PHP 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/python/index.html" target="_top" rel="nofollow">Netkiller Python 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/testing/index.html" target="_top" rel="nofollow">Netkiller Testing 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/cryptography/index.html" target="_top" rel="nofollow">Netkiller Cryptography 手札</a> </td> 
  </tr> 
  <tr> 
   <td> <a href="http://netkiller.github.io/linux/index.html" target="_top" rel="nofollow">Netkiller Linux 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/debian/index.html" target="_top" rel="nofollow">Netkiller Debian 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/centos/index.html" target="_top" rel="nofollow">Netkiller CentOS 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/freebsd/index.html" target="_top" rel="nofollow">Netkiller FreeBSD 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/shell/index.html" target="_top" rel="nofollow">Netkiller Shell 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/security/index.html" target="_top" rel="nofollow">Netkiller Security 手札</a> </td> 
  </tr> 
  <tr> 
   <td> <a href="http://netkiller.github.io/www/index.html" target="_top" rel="nofollow">Netkiller Web 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/monitoring/index.html" target="_top" rel="nofollow">Netkiller Monitoring 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/storage/index.html" target="_top" rel="nofollow">Netkiller Storage 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/mail/index.html" target="_top" rel="nofollow">Netkiller Mail 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/docbook/index.html" target="_top" rel="nofollow">Netkiller Docbook 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/version/index.html" target="_top" rel="nofollow">Netkiller Version 手札</a> </td> 
  </tr> 
  <tr> 
   <td> <a href="http://netkiller.github.io/database/index.html" target="_top" rel="nofollow">Netkiller Database 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/postgresql/index.html" target="_top" rel="nofollow">Netkiller PostgreSQL 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/mysql/index.html" target="_top" rel="nofollow">Netkiller MySQL 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/nosql/index.html" target="_top" rel="nofollow">Netkiller NoSQL 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/ldap/index.html" target="_top" rel="nofollow">Netkiller LDAP 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/network/index.html" target="_top" rel="nofollow">Netkiller Network 手札</a> </td> 
  </tr> 
  <tr> 
   <td> <a href="http://netkiller.github.io/cisco/index.html" target="_top" rel="nofollow">Netkiller Cisco IOS 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/h3c/index.html" target="_top" rel="nofollow">Netkiller H3C 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/multimedia/index.html" target="_top" rel="nofollow">Netkiller Multimedia 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/perl/index.html" target="_top" rel="nofollow">Netkiller Perl 手札</a> </td> 
   <td> <a href="http://netkiller.github.io/radio/index.html" target="_top" rel="nofollow">Netkiller Amateur Radio 手札</a> </td> 
   <td>   </td> 
  </tr> 
 </tbody> 
</table> 

目录

1. 背景

你是否有这样的需求:
你需要监控访问网站的IP,当同一个IP地址访问次数过多需要做出处理,例如拉黑,直接丢进iptables 防火墙规则连中。你的做法只能每个一段时间查询一次数据库,并且判断是否满足拉黑需求?
你是否需要监控某些数据发生变化,并通知其他程序作出处理。例如新闻内容修改后,需要立即做新页面静态化处理,生成新的静态页面
你使用数据库做队列,例如发送邮件,短信等等。你要通知发送程序对那些手机或者短线发送数据

2. 解决思路

需要让数据库与其他进程通信,传递信号
例如,发送短信这个需求,你只要告诉发短信的机器人发送的手机号码即可,机器人永远守候那哪里,只要命令一下立即工作。
监控数据库变化的需求原理类似,我们需要有一个守护进程等待命令,一旦接到下达命令便立即生成需要的静态页面
这里所提的方案是采用fifo(First In First Out)方案,通过管道相互传递信号,使两个进程协同工作,这样的效率远比定时任务高许多。fifo是用于操作系统内部进程间通信,如果跨越操作系统需要使用Socket,还有一个新名词MQ(Message queue).
这里只做fifo演示, 将本程序改为Socket方案,或者直接集成成熟的MQ也是分分钟可以实现。

3. Mysql plugin

我开发了几个 UDF, 共4个 function

UDF

fifo_create(pipename) 创建管道.成功返回true,失败返回flase.
fifo_remove(pipename) 删除管道.成功返回true,失败返回flase.
fifo_read(pipename) 读操作.
fifo_write(pipename,message) 写操作 pipename管道名,message消息正文.

有了上面的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 automake autoconf

https://github.com/netkiller/mysql-fifo-plugin
编译udf,最后将so文件复制到 /usr/lib/mysql/plugin/
git clone https://github.com/netkiller/mysql-image-plugin.git cd mysql-image-plugin

gcc -O3 -g -I/usr/include/mysql -I/usr/include -fPIC -lm -lz -shared -o fifo.so fifo.c sudo mv fifo.so /usr/lib/mysql/plugin/

装载
create function fifo_create returns string soname 'fifo.so'; create function fifo_remove returns string soname 'fifo.so'; create function fifo_read returns string soname 'fifo.so'; create function fifo_write returns string soname 'fifo.so';
卸载
drop function fifo_create; drop function fifo_remove; drop function fifo_read; drop function fifo_write;

5. 插件如何使用

插件有很多种用法,这里仅仅一个例

CREATE TABLE demo ( id INT(11) NULL DEFAULT NULL, name CHAR(10) NULL DEFAULT NULL, mobile VARCHAR(50) NULL DEFAULT NULL ) COLLATE='utf8_general_ci' ENGINE=InnoDB;

INSERT INTO demo (id, name, mobile) VALUES (1, 'neo', '13113668891'), (2, 'jam', '13113668892'), (3, 'leo', '13113668893');

我们假设有一个demo这样的表,我使用shell写了一个守护进程用于处理数据库送过来的数据
#!/bin/bash ########################################

Homepage: http://netkiller.github.io

Author: neo <netkiller@msn.com>

######################################## NAME=demo PIPE=/tmp/myfifo ######################################## LOGFILE=/tmp/$NAME.log PIDFILE=/tmp/${NAME}.pid ########################################

function start(){ if [ -f "$PIDFILE" ]; then exit 2 fi

    if [ ! -f "$LOGFILE" ]; then
            > ${LOGFILE}
    fi

for (( ; ; ))
do
        while read line
        do
			NOW=$(date '+%Y-%m-%d %H:%M:%S')
			
            echo "[${NOW}] [OK] ${line}" >> ${LOGFILE}

        done < $PIPE
done &
echo $! > $PIDFILE

} function stop(){ [ -f $PIDFILE ] && kill cat $PIDFILE && rm -rf $PIDFILE }

case "$1" in start) start ;; stop) stop ;; status) ps ax | grep ${0} | grep -v grep | grep -v status ;; restart) stop start ;; *) echo $"Usage: $0 {start|stop|status|restart}" exit 2 esac

exit $?

启动守护进程
$ ./sms.sh start $ ./sms.sh status 596 pts/5    S      0:00 /bin/bash ./sms.sh start
监控日志,因为守护进程没有输出,完成人户后写入日志。

$ tail -f /tmp/demo.log
开始推送任务
mysql> select fifo_write('/tmp/myfifo',concat(mobile,'\r\n')) from demo;
+-------------------------------------------------+
| fifo_write('/tmp/myfifo',concat(mobile,'\r\n')) |
+-------------------------------------------------+
| true                                            |
| true                                            |
| true                                            |
+-------------------------------------------------+
3 rows in set (0.00 sec)
现在看看日志的变化
$ tail -f /tmp/demo.log
[2013-12-16 14:55:48] [OK] 13113668891
[2013-12-16 14:55:48] [OK] 13113668892
[2013-12-16 14:55:48] [OK] 13113668893
我们再将上面的例子使用触发器进一步优化
CREATE TABLE `demo_sent` (
	`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
	`mobile` VARCHAR(50) NOT NULL,
	`status` ENUM('true','false') NOT NULL DEFAULT 'false',
	`ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
	PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB

CREATE DEFINER=`dba`@`%` TRIGGER `demo_after_insert` AFTER INSERT ON `demo` FOR EACH ROW BEGIN
	insert into demo_sent(mobile,status) select new.mobile,fifo_write('/tmp/myfifo',concat(new.mobile,'')) as status;
END
测试
mysql> insert into demo(name,mobile) values('jerry','13322993040');
Query OK, 1 row affected (0.05 sec)
日志变化
$ tail -f /tmp/demo.log 
[2013-12-16 14:55:48] [OK] 13113668891
[2013-12-16 14:55:48] [OK] 13113668892
[2013-12-16 14:55:48] [OK] 13113668893
[2013-12-16 14:55:48] [OK] 13322993040

6. 部署相关问题

我们可以采用主从数据库,将任务放在专用的从库上执行
我们可以创建很多个管道,用于做不同的工作,例如插入一个任务,更新一个任务,发短信一个任务,处理模板与静态化一个任务等等。

展开
收起
kun坤 2020-06-09 09:27:43 789 0
1 条回答
写回答
取消 提交回答
  • 不明觉厉啊######只是针对了mysql的插件开发解决,标题挂的是数据库会不会有点大了######请教下,这个思路能不能推广应用到其他几个主流数据库?如果可以,这标题就不仅不大,而且还很准确。######呵呵,不好意思,我正在写自己的数据库,所以你这个文我很喜欢。######好的,我抽时间学习研究下你这个。正好我很可能会用上。谢谢。######目前来说,很多数据库都很开放,都提供扩展开发,例如mysql开发一个插件,甚至数据库存储引擎都并非难事。######回复 @wharf_zhang : 我对oracle了解不多,oracle 官方应该有example 例子,下载下来改改,编译一下,就行了######oracle能弄个博文介绍下吗?商业的和开源的数据库,我个人感觉血统关系很弱,如果也能成立,则更能证明你这个思路具有普适性。######如果一个插件就搞定了 Mysql 的Cluster、 Oracle的OGG怎么活。######只能说你没有异构平台的通信需求,对实时性要求不高。######这个与Mysql 的Cluster、 Oracle的OGG没半毛关系######应用场景不同

    2020-06-09 09:27:52
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
阿里云&信通院《Serverless数据库技术研究报告》 立即下载
DTCC 2022大会集锦《云原生一站式数据库技术与实践》 立即下载
服务上云加速大家居产业C2M进程 立即下载