Nodejs 如何实时监测数据库变化?

Nodejs 如何实时监测数据库变化?

在用node.js做一个推送信息的模块,有个问题想请教下各位。

模块要推送的信息是存在MySQL中的。如何实现数据库中有新的信息插入的时候,就通知node.js进行推送呢?

我目前有两个想法: 1、nodejs对数据库进行轮询。 2、在MySQL中设置触发器,当有新数据插入时,触发器被触发,MySQL调用nodejs进行消息的推送,推送完再关掉nodejs。

这两种想法都不太好,各位Node.jser有什么好的思路么?

谢谢!

17 回复

标题:Node.js 如何实时监测数据库变化?

内容:

在使用 Node.js 开发一个推送信息的模块时,可能会遇到需要实时监测数据库变化的需求。例如,当你希望在 MySQL 数据库中新增一条记录时,能够立刻通过 Node.js 模块进行推送通知。直接使用轮询或者在 MySQL 中设置触发器来调用 Node.js 并不是最优的解决方案。接下来,我将介绍一种更高效的方法:使用数据库的变更日志(如 MySQL 的 binlog)和 WebSocket 进行实时通信。

方法概述

  1. 启用 MySQL 的 binlog:首先需要确保 MySQL 数据库启用了二进制日志(binlog),这样可以记录所有对数据库的更改操作。

  2. 使用 binlog 监听工具:使用如 mysql-binlog-connector 这样的工具监听 MySQL 的 binlog 变更,并通过网络发送这些变更到 Node.js 应用。

  3. WebSocket 实现实时推送:在 Node.js 应用中使用 WebSocket 技术,当接收到数据库变更通知时,立即向客户端推送更新信息。

示例代码

1. 启用 MySQL binlog

确保 MySQL 配置文件(通常是 my.cnf 或 my.ini)包含以下配置:

[mysqld]
server-id=1
log-bin=mysql-bin
binlog-format=ROW

重启 MySQL 服务以应用更改。

2. 使用 Node.js 和 WebSocket 实现推送

安装必要的包:

npm install mysql ws

创建一个简单的 Node.js 应用:

const express = require('express');
const WebSocket = require('ws');
const mysql = require('mysql');

const app = express();
const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
  console.log("A client connected.");
  
  // 当有新连接时,发送欢迎消息
  ws.send(JSON.stringify({ type: 'welcome', message: 'Welcome to the notification system!' }));
});

// 创建 MySQL 连接
const db = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'your_database'
});

db.connect();

// 监听数据库变化
db.query('SHOW BINLOG EVENTS LIMIT 1', (err, results) => {
  if (err) throw err;
  console.log(results);
});

console.log("Server is running on port 8080.");

app.listen(3000, () => console.log('App listening on port 3000!'));

注意:上述代码仅作为概念验证,实际生产环境中应使用专门的 binlog 监听工具,并且需要处理错误和断线重连逻辑。

这种方法避免了频繁查询数据库带来的性能开销,同时实现了真正的实时数据同步。


如果不用数据库自身提供通知功能,其他什么方法效率和实时性都不高,因为摆脱不了用轮询。与Nodejs、j2ee什么的没有任何关系。

Oracle有DCN机制,可以实现实时、精确的数据变化通知。

保存数据以后做消息广播?然后各种处理器各取所需?

你的推送对象是谁?是所有在线用户,还是所有用户!还是其他?

所有用户,不管是否在线。不在线的用户会收到一个提示

问题是java如何做消息广播,而nodejs又如何接收消息呢?有相应的事件么

多谢指点。

不在线的用户 上线之后 会收到一个新消息的提示,我可能没有表达清楚。

为什么用户需要同时和java与nodejs服务器建立连接呢?java需要做用户的验证么

hu.js是啥啊?朋友网是QQ那个?能否给个链接?

确实很不错,多谢!

最近也打算做类似的功能.
node.js + Socket.IO 做实时推送 Java 做主要实现 Java & node.js 之间使用 mq(ActiveMQ) 进行通讯

关于插入数据/数据改动的时候通知到bowser端. 这个在java模块提供支持. 对 pojo 做改动, 或者 dao 层做 insert/update 操作的时候, boardcast 到 mq 服务器, node.js(stomp模块) 接收到消息后, push 到bowser.

这篇文章不错: node.js 通过 zeromq, redis 和其他语言交互: http://www.gridshore.nl/2011/07/28/combining-java-and-node-js-through-redis-pubsub-and-a-json-remote-interface/

数据库有操作时候,往消息队列塞个值,去轮询这个队列。

轮询的话,效率还是有问题的

轮询是不科学的。 就像你说的。 1.在你保存数据到数据库的时候,同时调用nodejs推送接口 2.缓存,如redis,同样是在写数据库的同时往redis写消息队列,nodejs轮询redis消息队列。这个速度比轮询数据库要快。

最合理的方式用memcached,当PHP或者Java跟新数据库后,将需要传递给nodejs的数据同时插入memcached。nodejs用setTimeout(fn,msec),设定每秒轮询,这样效率就最高了。

其实上面大家都说了很多方案了,我补充一下吧, 用一种代理的设计模式就可以解决这个问题,统一控制插入接口入口,当有数据进行插入操作的时候,把要插入的接口加上一个中间键进行代理,而你只要控制代理实现推送就可以了。这样的话只要触发了插入就可以调用你自定义的推送方法,如果你不希望马上进行推送,需要定时推送也是没有问题的,把需要推送的数据插入到队列中,然后用nodejs默认的插件cron进行定时推送,当然也可以是py,rb,sh等,当你定时推送的时候还可以进行数据分析处理,这样可以在线和离线操作就可以分开

同意这个方案

存放推送消息队列这个功能,我个人建议还是放在内存里比较好,一条消息进入队列后很快就会被读到并且删掉,放在数据库里面磁盘io频率太高,用redis之类的服务存放会更好一些

对于实时监测数据库的变化,通常不建议使用轮询机制或在数据库中设置复杂的触发器来调用外部服务。这些方法不仅效率低下,还可能引入额外的性能开销。更好的解决方案是利用数据库自身提供的通知机制,或者使用中间件服务来监听变更事件。

对于 MySQL 数据库,你可以使用 mysql 模块结合 MySQL 的 performance_schema.events_waits_history 表或者使用 MySQL 的 binlog 来监听变更。不过,最简单的方式可能是使用 MySQL 的 INFORMATION_SCHEMA 或者直接通过轮询特定表的最后更新时间(但这仍然不是最优解)。

一个更现代的方法是使用具有内置变更流的数据库,如 MongoDB,它支持 WebSocket 和 Change Streams,或者使用 Redis,它提供了发布/订阅模型。如果必须使用 MySQL,可以考虑使用中间件服务,如 Debezium,它可以捕捉 MySQL 的 binlog 变更,并将这些变更推送到消息队列(如 Kafka),然后 Node.js 应用可以从消息队列中拉取变更并处理。

示例代码(假设使用 Redis)

首先,你需要安装 Redis 和 Redis 客户端:

npm install redis

然后,你可以编写 Node.js 代码来监听 Redis 的变更事件:

const redis = require('redis');
const subscriber = redis.createClient();

subscriber.on('message', (channel, message) => {
    console.log(`Received a message from ${channel}:`, message);
    // 在这里处理接收到的消息,比如推送通知
});

// 订阅特定的频道
subscriber.subscribe('data_update_channel');

console.log('Waiting for messages...');

在 MySQL 端,你可以配置一个脚本或者使用 Debezium 将变更事件发布到 Redis 的特定频道(例如 data_update_channel)。这样,你的 Node.js 应用就可以实时接收变更通知了。

这种方式避免了频繁查询数据库带来的性能问题,并且更加高效和灵活。

回到顶部