阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 多数据库连接管理

多数据库连接管理

作者:陈川 阅读数:32105人阅读 分类: MongoDB

多数据库连接管理

Mongoose作为Node.js中最流行的MongoDB ODM,提供了灵活的多数据库连接机制。实际项目中经常需要同时操作多个数据库实例,比如主从分离、分片集群或跨业务数据库访问等情况。

基本连接配置

创建单个数据库连接是基础场景,Mongoose通过mongoose.connect()实现:

const mongoose = require('mongoose');
const mainDB = mongoose.createConnection('mongodb://localhost:27017/main');

mainDB.on('connected', () => {
  console.log('Main DB connected');
});

mainDB.on('error', (err) => {
  console.error('Main DB connection error:', err);
});

多数据库连接则需要创建多个独立的connection实例。每个connection维护自己的连接池、模型定义和事务状态:

const userDB = mongoose.createConnection('mongodb://localhost:27017/users');
const productDB = mongoose.createConnection('mongodb://localhost:27017/products');

连接池优化

Mongoose默认每个连接池大小为5,高并发场景需要调整:

const options = {
  poolSize: 10, // 连接池大小
  bufferMaxEntries: 0, // 禁用缓冲
  connectTimeoutMS: 30000,
  socketTimeoutMS: 45000
};

const analyticsDB = mongoose.createConnection(
  'mongodb://cluster1.example.com:27017/analytics',
  options
);

不同业务场景建议采用差异化配置:

  • 高频查询:增大poolSize
  • 批量写入:保持较小poolSize但增加timeout
  • 报表数据库:设置readPreference=secondaryPreferred

模型绑定机制

在多数据库环境下,模型必须绑定到特定connection:

// 错误做法 - 模型会绑定到默认mongoose实例
// const User = mongoose.model('User', userSchema);

// 正确做法
const User = userDB.model('User', userSchema);
const Product = productDB.model('Product', productSchema);

动态模型注册方案:

function createModel(conn, modelName, schema) {
  if (conn.models[modelName]) {
    return conn.models[modelName];
  }
  return conn.model(modelName, schema);
}

const Order = createModel(orderDB, 'Order', orderSchema);

跨数据库事务

MongoDB 4.2+支持跨库事务,但需要特殊处理:

const session = await mainDB.startSession();
session.startTransaction();

try {
  const user = await User.create([{ name: 'Alice' }], { session });
  await Product.updateOne(
    { sku: '123' },
    { $inc: { stock: -1 } },
    { session: session }
  );
  await session.commitTransaction();
} catch (error) {
  await session.abortTransaction();
  throw error;
} finally {
  session.endSession();
}

连接状态监控

生产环境需要实时监控各连接状态:

function monitorConnections() {
  const connections = [mainDB, userDB, productDB];
  
  connections.forEach(conn => {
    console.log(`${conn.name} state:`, conn.readyState);
    // 0: disconnected
    // 1: connected
    // 2: connecting
    // 3: disconnecting
  });
}

setInterval(monitorConnections, 60000);

故障处理策略

网络波动时的重连机制:

function setupReconnect(conn, url) {
  conn.on('disconnected', () => {
    console.log(`Disconnected from ${conn.name}`);
    setTimeout(() => conn.openUri(url), 5000);
  });
}

setupReconnect(userDB, 'mongodb://localhost:27017/users');

多租户架构实现

SaaS应用中常见的多租户方案:

class TenantManager {
  constructor() {
    this.tenantConnections = new Map();
  }

  getTenantDB(tenantId) {
    if (this.tenantConnections.has(tenantId)) {
      return this.tenantConnections.get(tenantId);
    }

    const conn = mongoose.createConnection(
      `mongodb://cluster.example.com/${tenantId}`,
      { maxPoolSize: 5 }
    );
    
    this.tenantConnections.set(tenantId, conn);
    return conn;
  }
}

性能优化技巧

  1. 连接预热:
async function warmupConnection(conn) {
  await conn.collection('test').findOne({});
}
  1. 读写分离配置:
const readReplica = mongoose.createConnection('mongodb://replica1.example.com,replica2.example.com/db', {
  readPreference: 'secondary',
  replicaSet: 'rs0'
});
  1. 连接生命周期管理:
process.on('SIGINT', async () => {
  await Promise.all([
    mainDB.close(),
    userDB.close(false), // forceClose=false
    productDB.close(true) // forceClose=true
  ]);
  process.exit(0);
});

测试环境策略

自动化测试中的隔离方案:

beforeEach(async () => {
  testDB = mongoose.createConnection(
    'mongodb://localhost:27017/test',
    { poolSize: 1 }
  );
  await testDB.dropDatabase();
});

afterEach(async () => {
  await testDB.close();
});

配置最佳实践

推荐的生产环境配置模板:

const productionConfig = {
  autoIndex: false, // 生产环境禁用自动索引
  bufferCommands: false, // 禁用缓冲
  connectTimeoutMS: 30000,
  socketTimeoutMS: 45000,
  family: 4, // 强制IPv4
  keepAlive: true,
  keepAliveInitialDelay: 300000,
  maxPoolSize: 10,
  minPoolSize: 2,
  retryReads: true,
  retryWrites: true,
  serverSelectionTimeoutMS: 5000,
  heartbeatFrequencyMS: 10000
};

const prodDB = mongoose.createConnection(
  'mongodb+srv://prod.example.com/main',
  productionConfig
);

高级连接模式

  1. 动态路由连接:
function routeConnection(user) {
  return user.region === 'EU' ? 
    euDB : 
    asiaDB;
}
  1. 连接代理模式:
class DBProxy {
  constructor() {
    this.primary = primaryDB;
    this.secondary = secondaryDB;
  }

  query(options) {
    return options.readOnly ? 
      this.secondary : 
      this.primary;
  }
}
  1. 混合云连接方案:
const hybridDB = mongoose.createConnection([
  'mongodb://on-premise.example.com:27017/db',
  'mongodb://cloud-cluster.example.com:27017/db'
], {
  replicaSet: 'hybridSet',
  readPreference: 'nearest'
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌