🔄 Cấu Hình MongoDB Replica Set
📋 Quy Hoạch Hệ Thống
Tên | IP | Vai Trò |
---|---|---|
mongodb01 | 192.168.80.241 | Primary |
mongodb02 | 192.168.80.242 | Secondary |
mongodb03 | 192.168.80.243 | Secondary |
mongodb04 | 192.168.80.244 | Arbiter |
Giải Thích Về Các Node Trong Replica Set
- Primary: Node chính, nơi nhận tất cả các ghi (write) và thực hiện các thao tác cập nhật dữ liệu. Chỉ có một node primary tại một thời điểm.
- Secondary: Các node phụ, sao chép dữ liệu từ node primary. Chúng có thể xử lý các yêu cầu đọc (read) nếu được cấu hình cho phép.
- Arbiter: Node không lưu trữ dữ liệu, chỉ tham gia vào quá trình bầu cử để xác định node primary. Thường được sử dụng trong các cấu hình có số lượng node lẻ để đảm bảo có đủ phiếu bầu.
Số Lượng Node Trong Replica Set
- Một Replica Set tối thiểu cần có 3 node (1 primary và 2 secondary) để đảm bảo tính khả dụng và độ tin cậy.
- Có thể thêm nhiều node secondary hoặc arbiter tùy thuộc vào yêu cầu về hiệu suất và khả năng chịu lỗi.
Step 1 — Cấu Hình DNS
Chỉnh sửa file hosts trên tất cả VPS
sudo nano /etc/hosts
Thêm các dòng sau vào file:
192.168.80.241 mongodb01.replicaset.member
192.168.80.242 mongodb02.replicaset.member
192.168.80.243 mongodb03.replicaset.member
192.168.80.244 mongodb04.replicaset.member
Step 2 — Kích Hoạt Replication Trong File Cấu Hình MongoDB Của Mỗi Server
Cấu hình tất cả các server Mở file cấu hình:
sudo nano /etc/mongod.conf
Chỉnh sửa replicaset:
replSetName: mongodb-rs
Khởi động lại dịch vụ MongoDB:
sudo systemctl restart mongod
Thêm Replica
-
Đăng Nhập vào MongoDB:
- Sử dụng lệnh
mongosh
để đăng nhập vào MongoDB trên node hiện tại.
- Sử dụng lệnh
-
Đăng Nhập với Tài Khoản Có Đủ Quyền:
- Sử dụng lệnh
use admin
để chuyển sang database "admin" và sau đó sử dụng lệnhdb.auth(username, password)
để đăng nhập với một tài khoản có đủ quyền.
use admin
db.auth("your_username", "your_password") - Sử dụng lệnh
-
Khởi Tạo Replica Set:
- Sau khi bạn đã đăng nhập thành công, bạn có thể sử dụng lệnh
rs.initiate()
để khởi tạo replica set.
rs.initiate()
- Sau khi bạn đã đăng nhập thành công, bạn có thể sử dụng lệnh
-
Thêm Các Thành Viên Vào Replica Set:
- Sử dụng lệnh
rs.add()
để thêm các thành viên vào replica set:
rs.add("mongodb02.replicaset.member:27017")
rs.add("mongodb03.replicaset.member:27017") - Sử dụng lệnh
-
Thêm Arbiter (Lưu ý không thêm trên host the primary or the secondary members):
- Nếu bạn muốn thêm một thành viên Arbiter, bạn có thể sử dụng lệnh
rs.addArb()
:
rs.addArb("mongodb04.replicaset.member:27017")
- Nếu gặp lỗi:
rs.addArb("mongodb04.replicaset.member:27017");
MongoServerError: Reconfig attempted to install a config that would change the implicit default write concern. Use the setDefaultRWConcern command to set a cluster-wide write concern and try the reconfig again.Hãy thử:
db.adminCommand({
"setDefaultRWConcern" : 1,
"defaultWriteConcern" : {
"w" : 1
}
})Lưu ý: Thành viên Arbiter không lưu trữ dữ liệu, nó chỉ tham gia vào quá trình bầu.
- Nếu bạn muốn thêm một thành viên Arbiter, bạn có thể sử dụng lệnh
-
Kiểm Tra Trạng Thái Replica Set:
- Sử dụng lệnh
rs.status()
để kiểm tra trạng thái của replica set:
rs.status()
Kết quả mong đợi:
mongodb-rs [direct: primary] admin> rs.status()
{
set: 'mongodb-rs',
date: ISODate('2024-01-11T04:47:02.878Z'),
myState: 1,
term: Long('2'),
syncSourceHost: '',
syncSourceId: -1,
heartbeatIntervalMillis: Long('2000'),
majorityVoteCount: 2,
writeMajorityCount: 2,
votingMembersCount: 3,
writableVotingMembersCount: 3,
optimes: {
lastCommittedOpTime: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
lastCommittedWallTime: ISODate('2024-01-11T04:46:59.417Z'),
readConcernMajorityOpTime: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
appliedOpTime: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
durableOpTime: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
lastAppliedWallTime: ISODate('2024-01-11T04:46:59.417Z'),
lastDurableWallTime: ISODate('2024-01-11T04:46:59.417Z')
},
lastStableRecoveryTimestamp: Timestamp({ t: 1704948411, i: 1 }),
electionCandidateMetrics: {
lastElectionReason: 'electionTimeout',
lastElectionDate: ISODate('2024-01-11T04:44:11.112Z'),
electionTerm: Long('2'),
lastCommittedOpTimeAtElection: { ts: Timestamp({ t: 0, i: 0 }), t: Long('-1') },
lastSeenOpTimeAtElection: { ts: Timestamp({ t: 1704947370, i: 1 }), t: Long('1') },
numVotesNeeded: 1,
priorityAtElection: 1,
electionTimeoutMillis: Long('10000'),
numCatchUpOps: Long('0'),
newTermStartDate: ISODate('2024-01-11T04:44:11.121Z'),
wMajorityWriteAvailabilityDate: ISODate('2024-01-11T04:44:11.163Z')
},
members: [
{
_id: 0,
name: '192.168.80.241:27017',
health: 1,
state: 1,
stateStr: 'PRIMARY',
uptime: 188,
optime: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
optimeDate: ISODate('2024-01-11T04:46:59.000Z'),
lastAppliedWallTime: ISODate('2024-01-11T04:46:59.417Z'),
lastDurableWallTime: ISODate('2024-01-11T04:46:59.417Z'),
syncSourceHost: '',
syncSourceId: -1,
infoMessage: '',
electionTime: Timestamp({ t: 1704948251, i: 1 }),
electionDate: ISODate('2024-01-11T04:44:11.000Z'),
configVersion: 5,
configTerm: 2,
self: true,
lastHeartbeatMessage: ''
},
{
_id: 1,
name: 'mongodb02.replicaset.member:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 182,
optime: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
optimeDurable: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
optimeDate: ISODate('2024-01-11T04:46:59.000Z'),
optimeDurableDate: ISODate('2024-01-11T04:46:59.000Z'),
lastAppliedWallTime: ISODate('2024-01-11T04:46:59.417Z'),
lastDurableWallTime: ISODate('2024-01-11T04:46:59.417Z'),
lastHeartbeat: ISODate('2024-01-11T04:47:01.421Z'),
lastHeartbeatRecv: ISODate('2024-01-11T04:47:01.486Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: '192.168.80.241:27017',
syncSourceId: 0,
infoMessage: '',
configVersion: 5,
configTerm: 2
},
{
_id: 2,
name: 'mongodb03.replicaset.member:27017',
health: 1,
state: 2,
stateStr: 'SECONDARY',
uptime: 7,
optime: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
optimeDurable: { ts: Timestamp({ t: 1704948419, i: 1 }), t: Long('2') },
optimeDate: ISODate('2024-01-11T04:46:59.000Z'),
optimeDurableDate: ISODate('2024-01-11T04:46:59.000Z'),
lastAppliedWallTime: ISODate('2024-01-11T04:46:59.417Z'),
lastDurableWallTime: ISODate('2024-01-11T04:46:59.417Z'),
lastHeartbeat: ISODate('2024-01-11T04:47:01.421Z'),
lastHeartbeatRecv: ISODate('2024-01-11T04:47:01.927Z'),
pingMs: Long('0'),
lastHeartbeatMessage: '',
syncSourceHost: 'mongodb02.replicaset.member:27017',
syncSourceId: 1,
infoMessage: '',
configVersion: 5,
configTerm: 2
}
],
ok: 1,
'$clusterTime': {
clusterTime: Timestamp({ t: 1704948419, i: 1 }),
signature: {
hash: Binary.createFromBase64('OFBLEUZX/tt30FIpTA+tOofPrnw=', 0),
keyId: Long('7322670217476177927')
}
},
operationTime: Timestamp({ t: 1704948419, i: 1 })
}
mongodb-rs [direct: primary] admin>
(To exit, press Ctrl+C again or Ctrl+D or type .exit)
mongodb-rs [direct: primary] admin> - Sử dụng lệnh
Thêm/Xóa Node Trong Replica Set
Thêm Node Mới
-
Chuẩn Bị Node Mới:
- Cài đặt MongoDB với cùng phiên bản
- Cấu hình file hosts và mongod.conf
- Copy keyfile từ node primary (tham khảo hướng dẫn truyền file)
-
Thêm Node Secondary:
// Thêm node với priority mặc định (1)
rs.add("mongodb05.replicaset.member:27017")
// Hoặc thêm với cấu hình chi tiết
rs.add({
host: "mongodb05.replicaset.member:27017",
priority: 0.5, // Độ ưu tiên khi bầu primary
votes: 1 // Số phiếu trong quá trình bầu cử
})
Xóa Node
// Xóa node khỏi replica set
rs.remove("mongodb03.replicaset.member:27017")
Lưu ý khi xóa node
- Không xóa node primary trực tiếp
- Nếu cần xóa primary, trước tiên step down node đó:
rs.stepDown()
- Đảm bảo số node còn lại đủ để duy trì quorum
Cấu Hình Priority và Votes
// Thay đổi priority của node
cfg = rs.conf()
cfg.members[1].priority = 0.5 // Thay đổi priority của node thứ 2
rs.reconfig(cfg)
// Vô hiệu hóa quyền bầu cử của node
cfg.members[1].votes = 0
rs.reconfig(cfg)
Kiểm Tra và Bảo Trì Replica Set
1. Kiểm Tra Trạng Thái Chi Tiết
// Xem cấu hình hiện tại
rs.conf()
// Kiểm tra độ trễ sao chép
rs.printSecondaryReplicationInfo()
// Kiểm tra oplog
rs.printReplicationInfo()
2. Bảo Trì Node
// Tạm dừng sao chép trên secondary (để bảo trì)
db.fsyncLock()
// Khôi phục sao chép
db.fsyncUnlock()
Xử Lý Sự Cố Thường Gặp
-
Node Không Thể Tham Gia Replica Set
- Kiểm tra kết nối mạng giữa các node
- Xác nhận cấu hình DNS/hosts file
- Kiểm tra quyền của keyfile
- Đảm bảo phiên bản MongoDB khớp nhau
-
Node Secondary Không Đồng Bộ
// Kiểm tra trạng thái sao chép
rs.printSlaveReplicationInfo()
// Khởi động lại quá trình đồng bộ
rs.resync() -
Mất Node Primary
// Kiểm tra node nào đang là primary
rs.isMaster()
// Force bầu cử mới (nếu cần)
rs.reconfig(rs.conf(), {force: true})
Thực hành tốt
- Luôn duy trì số lượng node lẻ (3, 5, 7)
- Phân bố các node trên các server/datacenter khác nhau
- Cấu hình priority phù hợp với hiệu năng của từng node
- Monitoring thường xuyên trạng thái replica set
- Backup định kỳ trên node secondary