日志机制优化
- 日志预分配:通过调整
--logPrealloc
参数,开启日志预分配功能。在MongoDB启动时,预先分配日志文件空间,避免在高并发写入时频繁创建和扩展日志文件,减少I/O开销。例如,在配置文件中添加storage: logPrealloc: true
。
- 日志同步频率:修改
journalCommitIntervalMs
参数,该参数控制日志写入磁盘的频率。适当增加此值(默认100ms),可以减少磁盘I/O操作次数,但同时也会增加系统故障时数据丢失的风险。例如,将其调整为200ms:storage: journal: commitIntervalMs: 200
,需根据业务对数据一致性的要求谨慎调整。
成员级别持久性设置
- 副本集配置:在副本集架构中,合理设置成员角色。主节点负责接收写入操作,从节点负责数据复制和读操作。对于高并发写入场景,可适当增加从节点数量以分担读压力,同时确保有足够的节点用于数据复制,保证数据高可用性。例如,一个包含1个主节点、3个从节点和1个仲裁节点的副本集配置:
rs.initiate({
_id: "myReplSet",
members: [
{ _id: 0, host: "primary.example.com:27017" },
{ _id: 1, host: "secondary1.example.com:27017" },
{ _id: 2, host: "secondary2.example.com:27017" },
{ _id: 3, host: "secondary3.example.com:27017" },
{ _id: 4, host: "arbiter.example.com:27017", arbiterOnly: true }
]
});
- 优先级设置:为副本集成员设置合适的优先级,优先级高的节点更有可能成为主节点。对于具有更好硬件配置或网络条件的节点,可设置较高优先级,以确保在主节点故障转移时,能快速选出合适的新主节点,维持系统正常运行。例如,将性能较好的从节点优先级设置为2:
rs.reconfig({
_id: "myReplSet",
members: [
{ _id: 0, host: "primary.example.com:27017" },
{ _id: 1, host: "secondary1.example.com:27017", priority: 2 },
{ _id: 2, host: "secondary2.example.com:27017" },
{ _id: 3, host: "secondary3.example.com:27017" },
{ _id: 4, host: "arbiter.example.com:27017", arbiterOnly: true }
]
});
- 回滚设置:在副本集成员出现网络分区或故障恢复后,可能会发生回滚操作。为减少回滚对系统性能的影响,可通过调整
oplogSizeMB
参数,增大操作日志大小,使节点在故障恢复后能更好地追上主节点的状态,降低回滚的可能性。例如,将操作日志大小设置为1024MB:storage: oplogSizeMB: 1024
。
架构设计
- 分片集群:对于大规模高并发写入场景,采用分片集群架构。将数据按照一定的分片键(如时间戳、用户ID等)分布到多个分片上,每个分片可以是一个副本集。这样可以将写入负载分散到多个节点,提升整体写入性能。例如,按时间戳进行范围分片:
sh.addShard("shard1/member1.example.com:27017,member2.example.com:27017");
sh.addShard("shard2/member3.example.com:27017,member4.example.com:27017");
sh.enableSharding("myDB");
sh.shardCollection("myDB.myCollection", { timestamp: 1 });
- 客户端写入策略:在客户端采用合适的写入策略,如
w
参数控制写入操作在多少个节点确认后返回。对于高并发写入且对数据一致性要求较高的场景,可设置w: "majority"
,确保写入操作在大多数副本集成员确认后返回,保证数据的持久性和一致性。例如,在Node.js中使用MongoDB驱动:
const { MongoClient } = require('mongodb');
const uri = "mongodb://primary.example.com:27017,secondary1.example.com:27017,secondary2.example.com:27017/?replicaSet=myReplSet";
const client = new MongoClient(uri);
async function insertDocument() {
try {
await client.connect();
const database = client.db("myDB");
const collection = database.collection("myCollection");
const result = await collection.insertOne({ data: "example" }, { w: "majority" });
console.log(result);
} finally {
await client.close();
}
}
insertDocument();