Golang中国

背景:不想通过轮询访问的形式查询数据库,这样效率低而且占用CPU资源太大。所以想及时又低资源的方式获取到数据库里最新的信息。
自己看了看Mysql里的触发器,Mysql里的触发器能起到监听的作用,但是golang还是得不到触发器处理后的结果。所以想问问有什么好的法子能解决该问题呢?

21 回复
stevewang
#1 stevewang • 2015-08-13 16:14

你在数据库和访问数据的服务器之间加一个数据服务就可以了。

hezhixiong
#2 hezhixiong • 2015-08-13 17:14

没想明白新加的数据库如何把数据传入到golang,或者是golang如何及时的从新加的数据库里获得数据。能细说下原来么?

stevewang
#3 stevewang • 2015-08-13 17:15

不是数据库,是自己实现的数据服务。

hezhixiong
#4 hezhixiong • 2015-08-13 17:30

多谢提示,不过暂且没思路该怎么实现。

stevewang
#5 stevewang • 2015-08-13 17:37

不知道你的服务器架构。我估计是多个服务器,一个DB。
如果是这样,也可以另外建一个消息服务器(如ZeroMQ这样的),然后修改服务器逻辑:
1.服务器A向消息服务器订阅消息。
2.服务器B修改数据库以后,向消息服务器发送一条消息。
3.消息服务器把此消息广播给订阅者。
4.服务器A收到数据变更消息。
5.如果消息不含数据只含控制信息,服务器A需要再访问数据库获得变更后的数据。

hezhixiong
#6 hezhixiong • 2015-08-13 17:49

你这是消息队列,典型的生产者和消费者模式。而我的要求不是这样的。我的场景是:我要执行十个事务功能,且这十个事务功能都带有定时执行的参数,只需要golang依据各个事务不同配置参数定期执行任务。当然你很快会想到利用golang自动cron功能,我想过了cron不能满足需求。因为我想实现只修改需要执行的事务列表,golang服务器能动态实现这些事务,如果事务列表中B事务删除后,golang服务器能及时读取到B事务被删除从而删除B事务。
所以我期望仅仅是修改事务列表(该事务列表可以是存储在数据库,或redis或是其他配置文件),golang服务器不需要修改代码能及时读取到事务列表并定时实现事务列表。仁兄可有好的法子不?

ansinlee
#7 ansinlee • 2015-08-13 18:01

用tcpdump对数据库端口进行抓包,分析,完了扔给golang服务器

hezhixiong
#8 hezhixiong • 2015-08-13 18:08

tcpdump我曾经用过,每分钟抓取到的数据起码上KB了,虽然可以进行过滤,但是这个数据量还是很大的。而且觉得这个方法还不如轮询方式每分钟进行读取数据库。还有其他好的方法么?

ansinlee
#9 ansinlee • 2015-08-13 18:27

只抓写数据库的包,不抓数据库回包,应该量不是很大,每分钟上KB也没有多少吧

数据库好像没有回调通知外部服务的功能。

要完成回调功只能两种方法:

  1. 在golang 和 mysql数据库之间加一个服务拦截操作分析完成回调
  2. 利用tcpdump把操作复制一份分析后完成回调

第1种方法也要把所有数据都要经过中服务转发一下,第2种方法其实也是把所有数据包过滤一下,但感觉更底层的过滤应该快一点,而且对mysql和golang服务无影响

感觉还是写个触发器把变化写到数据表中,定时轮询比较好点

ansinlee
#10 ansinlee • 2015-08-13 18:27

只抓写数据库的包,不抓数据库回包,应该量不是很大,每分钟上KB也没有多少吧

数据库好像没有回调通知外部服务的功能。

要完成回调功只能两种方法:

  1. 在golang 和 mysql数据库之间加一个服务拦截操作分析完成回调
  2. 利用tcpdump把操作复制一份分析后完成回调

第1种方法也要把所有数据都要经过中服务转发一下,第2种方法其实也是把所有数据包过滤一下,但感觉更底层的过滤应该快一点,而且对mysql和golang服务无影响

感觉还是写个触发器把变化写到数据表中,定时轮询比较好点

ansinlee
#11 ansinlee • 2015-08-13 18:27

只抓写数据库的包,不抓数据库回包,应该量不是很大,每分钟上KB也没有多少吧

数据库好像没有回调通知外部服务的功能。

要完成回调功只能两种方法:

  1. 在golang 和 mysql数据库之间加一个服务拦截操作分析完成回调
  2. 利用tcpdump把操作复制一份分析后完成回调

第1种方法也要把所有数据都要经过中服务转发一下,第2种方法其实也是把所有数据包过滤一下,但感觉更底层的过滤应该快一点,而且对mysql和golang服务无影响

感觉还是写个触发器把变化写到数据表中,定时轮询比较好点

re661b
#12 re661b • 2015-08-13 18:45

MYSQL和应用中间建立一个代理,分析mysql协议,应用请求时记录数据,mysql处理完毕后在处理数据

stevewang
#13 stevewang • 2015-08-13 21:50

不太明白你的业务需求。

hezhixiong
#14 hezhixiong • 2015-08-14 09:16

回复ansinlee:我想通过你的第一种方案去实现,不过现在还没想好该怎么实现;至于第二个方案用轮询也就没什么好谈的了。
我的事务列表一览里也许一个月都不会变化,但是只要有变化就希望golang服务器能及时获取到最新的事务列表信息。所以用tcpdump抓包获取数据我认为不是理想的方案。
我先想想有没有好点的方案,最好是能监控到事务列表有变更然后不重启服务器的情况下更新服务器的事务信息。如果实在没想到好的方案,到时候再退而求其次,只要更新了事务列表就重启服务器,重新获取最新的事务列表的最新信息。

captain
#15 captain • 2015-08-14 15:09

监控mysql binlog

xulei8
#16 xulei8 • 2015-08-15 17:37

**很明显,这些方法都是不合理或代价太大的。

触发器可以实现类似的功能,但是,触发器无法调用其他的功能访问外部程序。
要实现这个功能,可以扩展mysql的功能。
请百度一下mysql udf .
就是用c写一个mysql插件,编译成.so或.dll,添加一个自定义function,这个function可以socket或其他方式通知你的程序就行了。
然后添加一个触发器。发现相应的操作时,使用这个function完成相应的操作。
google code上面有一个现成的。我以前用过。
http://blog.loftdigital.com/blog/how-to-write-mysql-functions-in-c 这里有一个例子。

hezhixiong
#17 hezhixiong • 2015-08-17 09:05

回复xulei8:太棒了,非常感谢。你这个方案不错。我先研究下,然后用C写一个mysql插件试试。

xjjrocker
#18 xjjrocker • 2016-11-18 11:42

mark一下好思路。

cougar
#19 cougar • 2016-11-18 22:46

Packetbeat, 以前用起来很好用,现在被加到ELK里面都不知道怎么玩了

原来不是要监控mysql,算了,这个是监控的方法

nuokesasi
#20 nuokesasi • 2016-11-19 12:38

还可以使用cgo来做
参考这个项目来实现write mysql function in go

方案和之前 @xulei8 的思路一样

https://github.com/dveeden/udf_fileexists_go

zhangcj
#21 zhangcj • 2016-11-28 12:56

可以在DAO将SQL传入DB的时候进行检测,查看SQL语句关键字

需要 登录 后方可回复, 如果你还没有账号你可以 注册 一个帐号。