nodejs多进程同一个数据库

2025-04-14 21

(www. n z w6.com)

nodejs多进程同一个数据库

在Node.js中,当多个进程需要同时访问同一个数据库时,可能会遇到连接池耗尽、数据竞争或锁等问题。为了解决这些问题,我们可以通过以下几种方法来优化和管理多进程对数据库的访问。

解决方案

  1. 使用独立的数据库连接池:每个进程都拥有自己的数据库连接池,避免进程间共享连接带来的问题。
  2. 通过消息队列解耦:将数据库操作封装到一个单独的服务中,其他进程通过消息队列与该服务通信。
  3. 集中式数据库管理服务:创建一个专门的数据库管理服务,所有进程通过网络请求与该服务交互。

接下来,我们将详细探讨每种解决方案,并提供示例代码。

1. 独立的数据库连接池

每个Node.js进程都可以维护自己的数据库连接池。这样可以确保每个进程都有独立的资源分配,避免了跨进程的连接争用。

示例代码

假设我们使用的是mysql2库来连接MySQL数据库:

javascript
const mysql = require('mysql2/promise');</p>

<p>async function createPool() {
    const pool = await mysql.createPool({
        host: 'localhost',
        user: 'root',
        password: 'password',
        database: 'test_db',
        waitForConnections: true,
        connectionLimit: 10, // 每个进程最多10个连接
        queueLimit: 0
    });
    return pool;
}</p>

<p>// 在每个进程中初始化数据库连接池
(async () => {
    const pool = await createPool();</p>

<pre><code>async function queryDatabase(sql, params) {
    const [rows] = await pool.execute(sql, params);
    return rows;
}

// 示例查询
const result = await queryDatabase('SELECT * FROM users WHERE id = ?', [1]);
console.log(result);

})();

2. 使用消息队列解耦

通过引入消息队列(如RabbitMQ、Kafka等),我们可以将数据库操作封装到一个独立的服务中,其他进程只需要发送消息给这个服务即可。

示例代码

数据库服务端(处理数据库请求)

javascript
const amqplib = require('amqplib/callback_api');
const mysql = require('mysql2/promise');</p>

<p>// 初始化数据库连接池
async function createPool() {
    const pool = await mysql.createPool({
        host: 'localhost',
        user: 'root',
        password: 'password',
        database: 'test_db',
        connectionLimit: 10
    });
    return pool;
}</p>

<p>const pool = createPool();</p>

<p>amqplib.connect('amqp://localhost', (err, conn) => {
    if (err) throw err;</p>

<pre><code>conn.createChannel((err, ch) => {
    if (err) throw err;

    const queue = 'db_queue';

    ch.assertQueue(queue, { durable: false });

    ch.consume(queue, async (msg) => {
        const content = JSON.parse(msg.content.toString());
        const sql = content.sql;
        const params = content.params;

        try {
            const [rows] = await pool.execute(sql, params);
            console.log('Query Result:', rows);
            ch.sendToQueue(msg.properties.replyTo, Buffer.from(JSON.stringify(rows)), { correlationId: msg.properties.correlationId });
            ch.ack(msg);
        } catch (error) {
            console.error('Error executing query:', error);
            ch.nack(msg);
        }
    }, { noAck: false });
});

});

客户端(发送数据库请求)

javascript
const amqplib = require('amqplib/callback_api');</p>

<p>amqplib.connect('amqp://localhost', (err, conn) => {
    if (err) throw err;</p>

<pre><code>conn.createChannel((err, ch) => {
    if (err) throw err;

    const queue = 'db_queue';
    const corr = generateUuid();

    ch.assertQueue('', { exclusive: true }, (err, q) => {
        if (err) throw err;

        console.log(' [*] Waiting for messages. To exit press CTRL+C');

        ch.consume(q.queue, (msg) => {
            if (msg.properties.correlationId === corr) {
                console.log(" [x] Received %s", msg.content.toString());
            }
        }, { noAck: true });

        const message = JSON.stringify({ sql: 'SELECT * FROM users WHERE id = ?', params: [1] });
        ch.sendToQueue(queue, Buffer.from(message), { correlationId: corr, replyTo: q.queue });
    });
});

});

function generateUuid() {
return Math.random().toString() + Math.random().toString() + Math.random().toString();
}

3. 集中式数据库管理服务

创建一个专门的HTTP服务来管理数据库操作,其他进程通过HTTP请求与该服务交互。

示例代码

数据库服务端(Express HTTP服务)

javascript
const express = require('express');
const mysql = require('mysql2/promise');</p>

<p>const app = express();
app.use(express.json());</p>

<p>// 初始化数据库连接池
async function createPool() {
    const pool = await mysql.createPool({
        host: 'localhost',
        user: 'root',
        password: 'password',
        database: 'test_db',
        connectionLimit: 10
    });
    return pool;
}</p>

<p>const pool = createPool();</p>

<p>app.post('/query', async (req, res) => {
    const { sql, params } = req.body;</p>

<pre><code>try {
    const [rows] = await pool.execute(sql, params);
    res.json(rows);
} catch (error) {
    console.error('Error executing query:', error);
    res.status(500).json({ error: 'Database error' });
}

});

app.listen(3000, () => {
console.log('Database service is running on port 3000');
});

客户端(发送HTTP请求)

javascript
const axios = require('axios');</p>

<p>async function queryDatabase(sql, params) {
    try {
        const response = await axios.post('http://localhost:3000/query', { sql, params });
        return response.data;
    } catch (error) {
        console.error('Error querying database:', error);
        throw error;
    }
}</p>

<p>// 示例查询
queryDatabase('SELECT * FROM users WHERE id = ?', [1])
    .then(result => console.log(result))
    .catch(error => console.error(error));

在Node.js多进程环境中,处理同一个数据库的访问有多种方式。独立的数据库连接池适合简单的应用场景;消息队列能够有效解耦业务逻辑与数据库操作;而集中式的数据库管理服务则提供了更高的灵活性和可扩展性。根据实际需求选择合适的方案,可以显著提升系统的性能和稳定性。

Image

1. 本站所有资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!cheeksyu@vip.qq.com
2. 本站不保证所提供下载的资源的准确性、安全性和完整性,资源仅供下载学习之用!如有链接无法下载、失效或广告,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!
4. 如果您也有好的资源或教程,您可以投稿发布,成功分享后有积分奖励和额外收入!
5.严禁将资源用于任何违法犯罪行为,不得违反国家法律,否则责任自负,一切法律责任与本站无关

源码下载