面试题答案
一键面试优化写入性能策略
- 批量写入:
- 使用
bulkWrite
操作,一次发送多个写入请求,减少客户端与MongoDB之间的网络通信开销。例如在Node.js中:
const MongoClient = require('mongodb').MongoClient; const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); async function bulkWriteDocs() { try { await client.connect(); const database = client.db('test'); const collection = database.collection('fixedColl'); const operations = [ { insertOne: { document: { data: 'doc1' } } }, { insertOne: { document: { data: 'doc2' } } } ]; const result = await collection.bulkWrite(operations); console.log(result); } finally { await client.close(); } } bulkWriteDocs();
- 使用
- 合理配置固定集合:
- 根据预计写入数据量和写入频率,预先设置合适的固定集合大小(
cappedSize
)和文档数量(cappedMax
)。如果设置过小,可能频繁触发数据淘汰,影响写入性能;设置过大则浪费磁盘空间。例如在创建固定集合时:
const MongoClient = require('mongodb').MongoClient; const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); async function createCappedColl() { try { await client.connect(); const database = client.db('test'); await database.createCollection('fixedColl', { capped: true, size: 1048576, max: 1000 }); console.log('Fixed collection created'); } finally { await client.close(); } } createCappedColl();
- 根据预计写入数据量和写入频率,预先设置合适的固定集合大小(
- 优化索引:
- 避免在固定集合上创建过多索引,因为索引维护会增加写入开销。仅创建必要的索引,例如查询中经常使用的字段索引。如果查询主要基于
timestamp
字段,可创建该字段的索引:
const MongoClient = require('mongodb').MongoClient; const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); async function createIndex() { try { await client.connect(); const database = client.db('test'); const collection = database.collection('fixedColl'); await collection.createIndex({ timestamp: 1 }); console.log('Index created'); } finally { await client.close(); } } createIndex();
- 避免在固定集合上创建过多索引,因为索引维护会增加写入开销。仅创建必要的索引,例如查询中经常使用的字段索引。如果查询主要基于
- 使用副本集:
- 配置MongoDB副本集,将写入操作分布到多个节点。主节点负责接收写入并将操作同步到从节点,从节点可以分担部分读操作压力,从而间接提升整体写入性能。例如在配置文件中设置副本集:
然后在初始化副本集时:replication: replSetName: myReplSet
const MongoClient = require('mongodb').MongoClient; const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); async function initiateReplSet() { try { await client.connect(); const adminDb = client.db('admin'); await adminDb.command({ replSetInitiate: { _id:'myReplSet', members: [ { _id: 0, host: 'localhost:27017' } ] } }); console.log('Replica set initiated'); } finally { await client.close(); } } initiateReplSet();
保证数据一致性策略
- 写关注(Write Concern):
- 根据应用对数据一致性的要求选择合适的写关注级别。例如,对于强一致性要求的场景,使用
w: "majority"
,确保写入操作在大多数副本集节点上持久化后才返回成功。在Node.js中:
const MongoClient = require('mongodb').MongoClient; const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); async function writeWithConcern() { try { await client.connect(); const database = client.db('test'); const collection = database.collection('fixedColl'); const result = await collection.insertOne({ data: 'doc' }, { writeConcern: { w: "majority" } }); console.log(result); } finally { await client.close(); } } writeWithConcern();
- 根据应用对数据一致性的要求选择合适的写关注级别。例如,对于强一致性要求的场景,使用
- 事务(Transactions):
- 如果写入操作涉及多个文档或集合的修改,且需要保证原子性,使用MongoDB的多文档事务。例如在Node.js中:
const MongoClient = require('mongodb').MongoClient; const uri = "mongodb://localhost:27017"; const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true }); async function multiDocTransaction() { try { await client.connect(); const session = client.startSession(); session.startTransaction(); const database = client.db('test'); const collection1 = database.collection('fixedColl1'); const collection2 = database.collection('fixedColl2'); await collection1.insertOne({ data: 'doc1' }, { session }); await collection2.insertOne({ relatedData: 'doc2' }, { session }); await session.commitTransaction(); console.log('Transaction committed'); } catch (e) { console.error('Transaction failed', e); } finally { await client.close(); } } multiDocTransaction();
- 定期验证和修复:
- 定期使用
db.collection.validate()
命令验证固定集合的数据一致性,及时发现并修复可能出现的数据损坏问题。例如在MongoDB shell中:
use test; db.fixedColl.validate();
- 定期使用