今日看了这篇博文:
https://medium.com/namely-labs/syncing-cache-with-postgres-7a4d78cec022
再一次感叹PG的强大。原来PG还可以通过pg_notify 这个方法,再加上触发器,去主动告诉外界数据的变化。
看了博文后,就用golang自己照着例子写了一个,以供参考:
package main import ( "database/sql" "fmt" "log" "time" "github.com/lib/pq" ) func main() { uri := "user=postgres password={YOUR_PASSWORD} host={YOUR_DB_HOST} port={YOUR_DB_PORT} dbname={YOUR_DB_NAME} sslmode=disable" db, err := sql.Open("postgres", uri) if err != nil { log.Fatal(err) } if err := db.Ping(); err != nil { log.Fatal(err) } report := func(et pq.ListenerEventType, err error) { if err != nil { fmt.Println(err) } } listener := pq.NewListener(uri, 10*time.Second, time.Minute, report) err = listener.Listen("hello") if err != nil { log.Fatal(err) } fmt.Println("-------start listen------------") for { n := <-listener.Notify switch n.Channel { case "hello": fmt.Println("get notify : ", n.Extra) } } }
代码的思路很简单,就是通过golang打开一个连接,然后用Listener去监听某一个Channel。在这里是一个叫"hello"的Channel。程序把Channel里面接收到的信息打印出来。
目前PG的pg_notify方法,只接受字符串,希望以后可以扩展,那样就不用再做数据类型的转换了。
当这个golang程序跑起来后,怎么测试效果呢? 最简单的方法,就是用pgAdmin连接到我们程序中的数据库,打开一个Query窗口,然后输入以下的命令并执行:
select pg_notify('hello', 'world');
一当执行这条SQL的时候,几乎同时在golang的程序就会打印出以下结果:
是不是觉得很神奇?反正我是,哈哈。
通过PG的这个机制,我们就可以让数据库”主动“地告诉我们什么数据更新了,从而可以触发其它动作。
不过这个机制只是类似于消息中间件的功能,但毕竟不是,它不会帮你存储消息,更不会持久化。当PG把消息发出去后,它是不会管是否有被监听的。换句话说,如果监听程序是在消息发送之前启动,它是不会获得以前的消息的。这点倒是要注意。如果对这一个特点比较介意的话,建议多开几个监听程序,或者用其它的方法来实现真正的消息中间件功能。