Skip to main content

🔄 Cấu Hình MongoDB Replica Set

📋 Quy Hoạch Hệ Thống

TênIPVai Trò
mongodb01192.168.80.241Primary
mongodb02192.168.80.242Secondary
mongodb03192.168.80.243Secondary
mongodb04192.168.80.244Arbiter

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

Cấu hình Replica Set

Khởi động lại dịch vụ MongoDB:

sudo systemctl restart mongod

Thêm Replica

  1. Đă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.
  2. Đă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ệnh db.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")
  3. 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()

    Khởi tạo Replica Set

  4. 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")

    Thêm Secondary Nodes

  5. 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.

  6. 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>

Thêm/Xóa Node Trong Replica Set

Thêm Node Mới

  1. 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)
  2. 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
  1. Không xóa node primary trực tiếp
  2. Nếu cần xóa primary, trước tiên step down node đó:
rs.stepDown()
  1. Đả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

  1. 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
  2. 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()
  3. 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
  1. Luôn duy trì số lượng node lẻ (3, 5, 7)
  2. Phân bố các node trên các server/datacenter khác nhau
  3. Cấu hình priority phù hợp với hiệu năng của từng node
  4. Monitoring thường xuyên trạng thái replica set
  5. Backup định kỳ trên node secondary

📚 Tài Liệu Tham Khảo