MST

星途 面试题库

面试题:Node.js Express集成PostgreSQL实现事务处理及性能优化

在Node.js的Express项目中集成PostgreSQL数据库,假设有两个表`accounts`(字段:`id`、`balance`)和`transactions`(字段:`id`、`from_account_id`、`to_account_id`、`amount`)。现在要实现一个转账功能,从一个账户向另一个账户转账一定金额,这个过程需要使用数据库事务来确保数据一致性。同时,要考虑在高并发场景下如何对该操作进行性能优化。请详细阐述实现思路,并给出核心代码示例及优化策略。
47.9万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 连接数据库:使用pg库连接到PostgreSQL数据库。
  2. 开启事务:在转账操作开始时,开启一个数据库事务,确保所有操作要么全部成功,要么全部失败。
  3. 检查账户余额:在转账前,查询转出账户的余额,确保余额足够。
  4. 更新账户余额:更新转出账户的余额(减少相应金额)和转入账户的余额(增加相应金额)。
  5. 记录交易:在transactions表中插入一条新的交易记录。
  6. 提交事务:如果所有操作都成功,提交事务;否则,回滚事务。
  7. 性能优化:在高并发场景下,可以考虑使用连接池管理数据库连接,减少连接创建和销毁的开销;对数据库表进行适当的索引优化,提高查询效率。

核心代码示例

const express = require('express');
const { Pool } = require('pg');

const app = express();
const pool = new Pool({
  user: 'your_user',
  host: 'your_host',
  database: 'your_database',
  password: 'your_password',
  port: 5432,
});

app.post('/transfer', async (req, res) => {
  const { fromAccountId, toAccountId, amount } = req.body;

  let client;
  try {
    client = await pool.connect();
    await client.query('BEGIN');

    const result = await client.query('SELECT balance FROM accounts WHERE id = $1', [fromAccountId]);
    if (result.rows[0].balance < amount) {
      throw new Error('Insufficient balance');
    }

    await client.query('UPDATE accounts SET balance = balance - $1 WHERE id = $2', [amount, fromAccountId]);
    await client.query('UPDATE accounts SET balance = balance + $1 WHERE id = $2', [amount, toAccountId]);
    await client.query('INSERT INTO transactions (from_account_id, to_account_id, amount) VALUES ($1, $2, $3)', [fromAccountId, toAccountId, amount]);

    await client.query('COMMIT');
    res.status(200).send('Transfer successful');
  } catch (e) {
    if (client) {
      await client.query('ROLLBACK');
    }
    res.status(500).send(`Transfer failed: ${e.message}`);
  } finally {
    if (client) {
      client.release();
    }
  }
});

const port = 3000;
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

优化策略

  1. 连接池优化:使用pg库的连接池(Pool),合理设置连接池的最大连接数、最小连接数等参数,避免频繁创建和销毁数据库连接。
  2. 索引优化:在accounts表的id字段和balance字段,以及transactions表的from_account_idto_account_id字段上创建索引,加快查询速度。
CREATE INDEX idx_accounts_id ON accounts (id);
CREATE INDEX idx_accounts_balance ON accounts (balance);
CREATE INDEX idx_transactions_from_account_id ON transactions (from_account_id);
CREATE INDEX idx_transactions_to_account_id ON transactions (to_account_id);
  1. 缓存机制:可以考虑对部分账户余额等常用数据进行缓存,减少数据库查询次数。例如使用Redis作为缓存层,在转账操作前先检查缓存中的余额,只有在缓存数据过期或不一致时才查询数据库。
  2. 负载均衡:如果是高并发场景,可以使用负载均衡器(如Nginx)将请求均匀分配到多个服务器实例上,减轻单个服务器的压力。
  3. 异步处理:确保在代码中尽可能使用异步操作,避免阻塞I/O操作,提高整体性能。如在上述代码中,使用await处理异步数据库操作。