๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
MongoDB/์šด์˜

MongoDB Primary Member ์„ ์ถœ์„ ๋ชปํ•  ๋•Œ ๋ณต๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•

by ๐ŸŒปโ™š 2023. 5. 5.

Replica Set์€ ๊ณผ๋ฐ˜์ˆ˜์˜ ๋ฉค๋ฒ„๊ฐ€ ์ •์ƒ์ผ ๋•Œ, Primary role์„ ๊ฐ–๋Š” Member๋ฅผ ์„ ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ๊ณผ๋ฐ˜์ˆ˜๋ฅผ ์ฑ„์šฐ์ง€ ๋ชปํ•˜๋ฉด Write๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ  Read๋งŒ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค. ์œ„์˜ ์˜ˆ์‹œ์ฒ˜๋Ÿผ 3๊ฐœ์ค‘ 1๊ฐœ ๋ฉค๋ฒ„๊ฐ€ ์ฃฝ์—ˆ์„ ๋•Œ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, 2๊ฐœ์˜ ๋ฉค๋ฒ„๊ฐ€ ์ฃฝ์œผ๋ฉด Primary Role์ด ์—†๋‹ค. ๋˜ํ•œ ๊ณผ๋ฐ˜์ˆ˜๋Š” Voting ๋ฉค๋ฒ„๋ฅผ ๊ธฐ์ค€์œผ๋กœํ•œ๋‹ค.

 

 

4๊ฐœ์˜ ๋ฉค๋ฒ„๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ–ˆ์„ ๋•Œ ๊ณผ๋ฐ˜์ˆ˜๋Š” 3๊ฐœ์ด๋‹ค. ํ•˜์ง€๋งŒ, MongoDB์˜ ์„ ์ถœ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ voting member๋ฅผ ๊ธฐ์ค€์œผ๋กœํ•˜๊ธฐ ๋•Œ๋ฌธ์— Replica Set ๊ตฌ์„ฑ์ด 4๊ฐœ์ด๋”๋ผ๋„ 3๊ฐœ ๋ฉค๋ฒ„์—์„œ๋งŒ ์„ ์ถœ์ž‘์—…์„ ์ง„ํ–‰ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์œ„์˜ ์ด๋ฏธ์ง€์ฒ˜๋Ÿผ voting๋ฉค๋ฒ„ 3๊ฐœ ์ค‘ ๊ณผ๋ฐ˜์ˆ˜์ธ 2๊ฐœ ๋ฉค๋ฒ„๋งŒ ์‚ด์•„ ์žˆ๋‹ค๋ฉด Primary๋ฅผ ์„ ์ถœํ•œ๋‹ค. ์ฐธ๊ณ ๋กœ MongoDB๋Š” ์ตœ๋Œ€ 7๊ฐœ์˜ Voting ๋ฉค๋ฒ„๋ฅผ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๊ณ  ์ตœ๋Œ€ 50๊ฐœ์˜ ๋ฉค๋ฒ„๋ฅผ Replica Set์œผ๋กœ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

๊ณผ๋ฐ˜์ˆ˜ ํ…Œ์ŠคํŠธ (3 Member)

์ƒํƒœ ํ™•์ธ

rs_1 [direct: primary] test> rs.status().members
[
  {
    _id: 0,
    name: '__HOST1__:27017',
    health: 1,
    state: 2,
    stateStr: 'SECONDARY',
    uptime: 74756,
    optime: { ts: Timestamp({ t: 1683264809, i: 1 }), t: Long("11") },
    optimeDurable: { ts: Timestamp({ t: 1683264809, i: 1 }), t: Long("11") },
    optimeDate: ISODate("2023-05-05T05:33:29.000Z"),
    optimeDurableDate: ISODate("2023-05-05T05:33:29.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:33:29.680Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:33:29.680Z"),
    lastHeartbeat: ISODate("2023-05-05T05:33:31.355Z"),
    lastHeartbeatRecv: ISODate("2023-05-05T05:33:31.355Z"),
    pingMs: Long("0"),
    lastHeartbeatMessage: '',
    syncSourceHost: '__HOST3__:27017',
    syncSourceId: 2,
    infoMessage: '',
    configVersion: 7,
    configTerm: 11
  },
  {
    _id: 1,
    name: '__HOST2__:27017',
    health: 1,
    state: 2,
    stateStr: 'SECONDARY',
    uptime: 948956,
    optime: { ts: Timestamp({ t: 1683264809, i: 1 }), t: Long("11") },
    optimeDurable: { ts: Timestamp({ t: 1683264809, i: 1 }), t: Long("11") },
    optimeDate: ISODate("2023-05-05T05:33:29.000Z"),
    optimeDurableDate: ISODate("2023-05-05T05:33:29.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:33:29.680Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:33:29.680Z"),
    lastHeartbeat: ISODate("2023-05-05T05:33:32.284Z"),
    lastHeartbeatRecv: ISODate("2023-05-05T05:33:31.539Z"),
    pingMs: Long("0"),
    lastHeartbeatMessage: '',
    syncSourceHost: '__HOST3__:27017',
    syncSourceId: 2,
    infoMessage: '',
    configVersion: 7,
    configTerm: 11
  },
  {
    _id: 2,
    name: '__HOST3__:27017',
    health: 1,
    state: 1,
    stateStr: 'PRIMARY',
    uptime: 1814026,
    optime: { ts: Timestamp({ t: 1683264809, i: 1 }), t: Long("11") },
    optimeDate: ISODate("2023-05-05T05:33:29.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:33:29.680Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:33:29.680Z"),
    syncSourceHost: '',
    syncSourceId: -1,
    infoMessage: '',
    electionTime: Timestamp({ t: 1682315664, i: 1 }),
    electionDate: ISODate("2023-04-24T05:54:24.000Z"),
    configVersion: 7,
    configTerm: 11,
    self: true,
    lastHeartbeatMessage: ''
  }
]

3๊ฐœ์˜ ๋ฉค๋ฒ„๊ฐ€ ์ •์ƒ์ธ ์ƒํƒœ์ด๊ณ  1๊ฐœ์˜ Primary์™€ 2๊ฐœ์˜ Secondary๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.

 

 

rs_1 [direct: primary] test> rs.conf()
{
  _id: 'rs_1',
  version: 7,
  term: 11,
  members: [
    {
      _id: 0,
      host: '__HOST1__:27017',
      arbiterOnly: false,
      buildIndexes: true,
      hidden: false,
      priority: 1,
      tags: {},
      secondaryDelaySecs: Long("0"),
      votes: 1
    },
    {
      _id: 1,
      host: '__HOST2__:27017',
      arbiterOnly: false,
      buildIndexes: true,
      hidden: false,
      priority: 1,
      tags: {},
      secondaryDelaySecs: Long("0"),
      votes: 1
    },
    {
      _id: 2,
      host: '__HOST3__:27017',
      arbiterOnly: false,
      buildIndexes: true,
      hidden: false,
      priority: 1,
      tags: {},
      secondaryDelaySecs: Long("0"),
      votes: 1
    }
  ],
  protocolVersion: Long("1"),
  writeConcernMajorityJournalDefault: true,
  settings: {
    chainingAllowed: true,
    heartbeatIntervalMillis: 2000,
    heartbeatTimeoutSecs: 10,
    electionTimeoutMillis: 10000,
    catchUpTimeoutMillis: -1,
    catchUpTakeoverDelayMillis: 30000,
    getLastErrorModes: {},
    getLastErrorDefaults: { w: 1, wtimeout: 0 },
    replicaSetId: ObjectId("63ae7ae46d30e0748a16a7d3")
  }
}

Replica Set์˜ ๋ฉค๋ฒ„ ์ƒํƒœ๋ฅผ ๋ณด๋ฉด, ๋ชจ๋‘ ์•„๋ž˜์™€ ๊ฐ™์€ ์„ค์ •์„ ๊ฐ–๋Š”๋‹ค.

  • hidden: false
  • priority: 1
  • votes: 1

ํ˜„์žฌ๋Š” Read์™€ Write ๋ชจ๋‘ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ์ด๋‹ค.

 

1 Member Down

rs_1 [direct: secondary] test> db.shutdownServer()

Secondary ๋ฉค๋ฒ„ ํ•˜๋‚˜๋ฅผ ์ฃฝ์ด๊ณ  ๋‹ค์‹œ ์ƒํƒœ๋ฅผ ํ™•์ธํ•œ๋‹ค.

 

 

rs_1 [direct: primary] test> rs.status().members
[
  {
    _id: 0,
    name: '__HOST1__:27017',
    health: 0,
    state: 8,
    stateStr: '(not reachable/healthy)',
    uptime: 0,
    optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long("-1") },
    optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long("-1") },
    optimeDate: ISODate("1970-01-01T00:00:00.000Z"),
    optimeDurableDate: ISODate("1970-01-01T00:00:00.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:39:39.694Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:39:39.694Z"),
    lastHeartbeat: ISODate("2023-05-05T05:40:07.369Z"),
    lastHeartbeatRecv: ISODate("2023-05-05T05:39:47.359Z"),
    pingMs: Long("0"),
    lastHeartbeatMessage: 'Error connecting to __HOST1__:27017 (__IP1__:27017) :: caused by :: Connection refused',
    syncSourceHost: '',
    syncSourceId: -1,
    infoMessage: '',
    configVersion: 7,
    configTerm: 11
  },
  {
    _id: 1,
    name: '__HOST2__:27017',
    health: 1,
    state: 2,
    stateStr: 'SECONDARY',
    uptime: 949352,
    optime: { ts: Timestamp({ t: 1683265199, i: 1 }), t: Long("11") },
    optimeDurable: { ts: Timestamp({ t: 1683265199, i: 1 }), t: Long("11") },
    optimeDate: ISODate("2023-05-05T05:39:59.000Z"),
    optimeDurableDate: ISODate("2023-05-05T05:39:59.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:39:59.695Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:39:59.695Z"),
    lastHeartbeat: ISODate("2023-05-05T05:40:08.317Z"),
    lastHeartbeatRecv: ISODate("2023-05-05T05:40:07.622Z"),
    pingMs: Long("0"),
    lastHeartbeatMessage: '',
    syncSourceHost: '__HOST3__:27017',
    syncSourceId: 2,
    infoMessage: '',
    configVersion: 7,
    configTerm: 11
  },
  {
    _id: 2,
    name: '__HOST3__:27017',
    health: 1,
    state: 1,
    stateStr: 'PRIMARY',
    uptime: 1814421,
    optime: { ts: Timestamp({ t: 1683265199, i: 1 }), t: Long("11") },
    optimeDate: ISODate("2023-05-05T05:39:59.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:39:59.695Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:39:59.695Z"),
    syncSourceHost: '',
    syncSourceId: -1,
    infoMessage: '',
    electionTime: Timestamp({ t: 1682315664, i: 1 }),
    electionDate: ISODate("2023-04-24T05:54:24.000Z"),
    configVersion: 7,
    configTerm: 11,
    self: true,
    lastHeartbeatMessage: ''
  }
]

0๋ฒˆ ๋ฉค๋ฒ„๋Š” ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ์ด์ง€๋งŒ, 1๋ฒˆ๊ณผ 2๋ฒˆ์€ ๊ฐ๊ฐ ์‚ด์•„์žˆ๊ณ  Secondary์™€ Primary role์„ ๊ฐ–๋Š”๋‹ค.

 

 

2 Member Down

rs_1 [direct: secondary] test> db.shutdownServer()

๋™์ผํ•˜๊ฒŒ ๋‹ค๋ฅธ Secondary Member๋ฅผ ์ฃฝ์ธ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ƒํƒœ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•œ๋‹ค.

 

 

rs_1 [direct: secondary] test> rs.status().members
[
  {
    _id: 0,
    name: '__HOST1__:27017',
    health: 0,
    state: 8,
    stateStr: '(not reachable/healthy)',
    uptime: 0,
    optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long("-1") },
    optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long("-1") },
    optimeDate: ISODate("1970-01-01T00:00:00.000Z"),
    optimeDurableDate: ISODate("1970-01-01T00:00:00.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:39:39.694Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:39:39.694Z"),
    lastHeartbeat: ISODate("2023-05-05T05:44:03.013Z"),
    lastHeartbeatRecv: ISODate("2023-05-05T05:39:47.359Z"),
    pingMs: Long("0"),
    lastHeartbeatMessage: 'Error connecting to replica-50-001-mongo-v-jp2v-dev.lineinfra-dev.com:20011 (10.241.152.125:20011) :: caused by :: Connection refused',
    syncSourceHost: '',
    syncSourceId: -1,
    infoMessage: '',
    configVersion: 7,
    configTerm: 11
  },
  {
    _id: 1,
    name: '__HOST2__:27017',
    health: 0,
    state: 8,
    stateStr: '(not reachable/healthy)',
    uptime: 0,
    optime: { ts: Timestamp({ t: 0, i: 0 }), t: Long("-1") },
    optimeDurable: { ts: Timestamp({ t: 0, i: 0 }), t: Long("-1") },
    optimeDate: ISODate("1970-01-01T00:00:00.000Z"),
    optimeDurableDate: ISODate("1970-01-01T00:00:00.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:43:19.702Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:43:19.702Z"),
    lastHeartbeat: ISODate("2023-05-05T05:44:02.860Z"),
    lastHeartbeatRecv: ISODate("2023-05-05T05:43:29.690Z"),
    pingMs: Long("0"),
    lastHeartbeatMessage: 'Error connecting to replica-50-002-mongo-v-jp2v-dev.lineinfra-dev.com:20011 (10.241.152.126:20011) :: caused by :: Connection refused',
    syncSourceHost: '',
    syncSourceId: -1,
    infoMessage: '',
    configVersion: 7,
    configTerm: 11
  },
  {
    _id: 2,
    name: '__HOST3__:27017',
    health: 1,
    state: 2,
    stateStr: 'SECONDARY',
    uptime: 1814656,
    optime: { ts: Timestamp({ t: 1683265409, i: 1 }), t: Long("11") },
    optimeDate: ISODate("2023-05-05T05:43:29.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T05:43:29.702Z"),
    lastDurableWallTime: ISODate("2023-05-05T05:43:29.702Z"),
    syncSourceHost: '',
    syncSourceId: -1,
    infoMessage: '',
    configVersion: 7,
    configTerm: 11,
    self: true,
    lastHeartbeatMessage: ''
  }
]

3๊ฐœ์˜ ๋ฉค๋ฒ„ ์ค‘ 2๊ฐœ์˜ ๋ฉค๋ฒ„๊ฐ€ ์ฃฝ์€ ์ƒํƒœ์ด๋‹ค. Replica Set์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ–ˆ์„ ๋•Œ, Primary๋Š” ์—†๊ณ  Secondary๋งŒ ๋‚จ์•„์žˆ๋Š” ์ƒํ™ฉ์ด๋‹ค. 3๊ฐœ์˜ ๊ณผ๋ฐ˜์ˆ˜์ธ 2๊ฐœ์˜ ๋ฉค๋ฒ„๊ฐ€ ์ •์ƒ์ด์ง€ ๋ชปํ•˜์—ฌ Primary๋ฅผ ์„ ์ถœํ•˜์ง€ ๋ชปํ•˜๊ณ  ์žˆ๋‹ค. ์‹ค์ œ 3๊ฐœ์˜ ๋ฉค๋ฒ„๋กœ ์šด์˜๋˜๋Š” MongoDB๋ผ๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ, ๋ชจ๋“  ๋ฉค๋ฒ„๊ฐ€ ์ฃฝ๋Š” ๊ฒฝ์šฐ๋Š” ์˜์™ธ๋กœ ๋Œ€๋Ÿ‰์˜ ๋ถ€ํ•˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, 2๊ฐœ์˜ ๋ฉค๋ฒ„๋งŒ ์ฃฝ๋Š” ๊ฒฝ์šฐ๋Š” ๋งค์šฐ ๋“œ๋ฌผ๋‹ค. ํ•˜์ง€๋งŒ, ์–ธ์ œ ์–ด๋–ป๊ฒŒ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ• ์ง€ ์šฐ๋ฆฌ๋Š” ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ๊ณผ๋ฐ˜์ˆ˜๋ฅผ ์ฑ„์šฐ์ง€ ๋ชปํ•˜์—ฌ Primary Member๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผํ•˜๋Š”์ง€ ๋ฏธ๋ฆฌ ์•Œ์•„๋ณด์ž.

 

 

์ž„์‹œ์  Standalone ๋ณต๊ตฌ

Replica Set ๊ตฌ์„ฑ์€ ๋ชจ๋“  ๋ฉค๋ฒ„๊ฐ€ ๋™์ผํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋“ค๊ณ  ์žˆ๋‹ค. Read/Write ๋ชจ๋‘ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ณผ๋ฐ˜์ˆ˜๊ฐ€ ์ •์ƒ์ด์–ด์•ผํ•œ๋‹ค. ๊ทธ๋Ÿผ ์œ„์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ 2๊ฐ€์ง€์ด๋‹ค.

  • ๋ฉค๋ฒ„๋ฅผ ๋Š˜๋ฆฌ๊ฑฐ๋‚˜
  • ๋ฉค๋ฒ„๋ฅผ ์ค„์ด๊ฑฐ๋‚˜

๋ฉค๋ฒ„๋ฅผ ๋Š˜๋ฆด  ๊ฒฝ์šฐ, MongoDB ์„ค์น˜๊นŒ์ง€ ์™„๋ฃŒ๋œ ์ฆ‰, ๋ฐ”๋กœ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ์ค€๋น„๋œ ์„œ๋ฒ„๊ฐ€ ์žˆ์–ด์•ผํ•˜๋Š”๋ฐ... ์„œ๋ฒ„๊ฐ€ ์žˆ๋‹ค๊ณ ํ•˜๋”๋ผ๋„ ๋ฐ์ดํ„ฐ ์–‘์— ๋”ฐ๋ผ ๋ณต๊ตฌ ์‹œ๊ฐ„ ์ฐจ์ด๊ฐ€ ํฌ๊ฒŒ ๋‚  ๊ฒƒ์ด๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ์ ์œผ๋ฉด Initial Sync๋กœ ๊ธˆ๋ฐฉ ๋ณต์ œ๋ฅผ ๋”ฐ๋ผ๊ฐˆ ์ˆ˜ ์žˆ์ง€๋งŒ... ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ์ผ ๊ฒฝ์šฐ, Initial Sync๋Š” ๋‹น์—ฐํ•˜๊ณ  ๋ฐฑ์—…์„ ๋ณต์‚ฌํ•˜๋Š” ๋ฐฉ์‹๋„ ํฌ๊ธฐ์— ๋”ฐ๋ผ ๋น„๋ก€์ ์œผ๋กœ ์˜ค๋ž˜ ๊ฑธ๋ฆด ๊ฒƒ์ด๋‹ค.

 

Primary ์„ ์ถœ์„ ๋ชปํ•˜๋Š” ์žฅ์• ๋Š” Write๋ฅผ ํ•  ์ˆ˜ ์—†๋Š” ๋งค์šฐ ๊ธด๊ธ‰ํ•œ ์žฅ์• ๋กœ, ์‘๊ธ‰์ฒ˜์น˜์„ฑ์œผ๋กœ ์ผ๋‹จ ๋ชจ๋“  ๊ธฐ๋Šฅ์ด ์ •์ƒ ์ž‘๋™ํ•˜๋„๋ก ์กฐ์ทจํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค. ๊ทธ๋ž˜์„œ ๋ฉค๋ฒ„๋ฅผ ๋Š˜๋ฆฌ๋Š” ๊ฒƒ ๋ณด๋‹ค ๋ฉค๋ฒ„๋ฅผ ์ค„์—ฌ์„œ ์ผ์‹œ์ ์œผ๋กœ 1๊ฐœ์˜ ๋ฉค๋ฒ„๋ฅผ ๊ฐ–๋Š” Standalone ํ˜•ํƒœ๋กœ ๋ณต๊ตฌํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ๋น ๋ฅผ ๊ฒƒ์ด๋‹ค. ์ฆ‰, 3๊ฐœ ๋ฉค๋ฒ„์ค‘ 2๊ฐœ ๋ฉค๋ฒ„๋ฅผ Replica Set์—์„œ ์ œ๊ฑฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๋‹จ ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์€ ๊ณ ๋ คํ•ด์•ผํ•œ๋‹ค.

  • ๊ธฐ์กด Write ํŠธ๋ž˜ํ”ฝ๊ณผ ๋ชจ๋“  Read๊ฐ€ ํ•˜๋‚˜์˜ ์„œ๋ฒ„์—์„œ ๊ฐ๋‹นํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค. Read๊ฐ€ ์—ฌ๋Ÿฌ๋Œ€์˜ Secondary๋กœ ๋ถ„์‚ฐ๋˜๊ณ  ์žˆ์—ˆ๊ณ  Write๋„ ๋งŽ์€ ์„œ๋น„์Šค์˜€๋‹ค๋ฉด ์ตœ์•…์˜ ๊ฒฝ์šฐ, ํ•˜๋‚˜์˜ ์„œ๋ฒ„์—์„œ ๋ชจ๋“  ํŠธ๋ž˜ํ”ฝ์„ ๊ฐ๋‹นํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋‚จ์€ ์„œ๋ฒ„ ํ•˜๋‚˜๋„ ์ฃฝ์„ ์ˆ˜ ์žˆ๋‹ค.
  • Application๋‹จ์—์„œ Read Preference๊ฐ€ secondary์˜€๋‹ค๋ฉด Primary๊ฐ€ ํ•˜๋‚˜๋งŒ ๋‚จ์•˜์„ ๋•Œ, Write๋Š” ๋˜๊ฒ ์ง€๋งŒ ์˜คํžˆ๋ ค ๋ฐ˜๋Œ€๋กœ Read๊ฐ€ ์•ˆ๋  ์ˆ˜ ์žˆ๋‹ค.

์ž ๊ทธ๋Ÿผ ์œ„์˜ ๊ณ ๋ ค์‚ฌํ•ญ์„ ๋ฐฐ์ œํ•˜๊ณ ... ๋ณต๊ตฌํ•˜๋Š” ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋ ค๋Š”๋ฐ...

 

rs_1 [direct: secondary] test> rs.remove('__HOST1__:27017')
MongoServerError: New config is rejected :: caused by :: replSetReconfig should only be run on a writable PRIMARY. Current state SECONDARY;

 

์œ„์— ์ฒ˜๋Ÿผ remove ๋ช…๋ น์œผ๋กœ Replica Set Member๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๋ฐฉ์‹์ด 1์ฐจ์ ์œผ๋กœ ์ƒ๊ฐ๋‚˜๊ฒ ์ง€๋งŒ... ๋ช…๋ น ์ˆ˜ํ–‰์ด ์•ˆ๋œ๋‹ค. ์ด์œ ๋Š” Secondary์—์„œ ์ˆ˜ํ–‰ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค. ๋น ๋ฅธ ๋ณต๊ตฌ๊ฐ€ ํ•„์š”ํ•œ ์‘๊ธ‰ ์ƒํ™ฉ์—์„œ ๋‚ด๊ฐ€ ์˜ˆ์ƒํ•œ๋Œ€๋กœ ์ง„ํ–‰๋˜์ง€ ์•Š์œผ๋ฉด... ์ผ๋‹จ ์‹ฌ์žฅ๋ถ€ํ„ฐ ๋ฉŽ๋Š” ๊ธฐ๋ถ„์ด๊ณ  ์†Œ๋ฆ„ ์ซ™ ๋ผ์น˜๋ฉด์„œ ๋งค์šฐ ๋‹นํ™ฉ์Šค๋Ÿฌ์šธ ๊ฒƒ์ด๋‹ค. ใ…Žใ…Ž ์•„๋ž˜ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์ž.

 

 

# ํ˜„์žฌ ์‚ด์•„์žˆ๋Š” ๋ฉค๋ฒ„์˜ ๋ฐฐ์—ด ์œ„์น˜๋ฅผ ํ™•์ธํ•œ๋‹ค.
rs_1 [direct: secondary] test> rs.conf().members

rs_1 [direct: secondary] test> conf = rs.conf()
rs_1 [direct: secondary] test> conf.members = [conf.members[2]]
rs_1 [direct: secondary] test> rs.reconfig(conf, {force: true})

rs_1 [direct: primary] test> rs.status().members
[
  {
    _id: 2,
    name: '__HOST3__:27017',
    health: 1,
    state: 1,
    stateStr: 'PRIMARY',
    uptime: 1817126,
    optime: { ts: Timestamp({ t: 1683267912, i: 1 }), t: Long("15") },
    optimeDate: ISODate("2023-05-05T06:25:12.000Z"),
    lastAppliedWallTime: ISODate("2023-05-05T06:25:12.021Z"),
    lastDurableWallTime: ISODate("2023-05-05T06:25:12.021Z"),
    syncSourceHost: '',
    syncSourceId: -1,
    infoMessage: '',
    electionTime: Timestamp({ t: 1683267821, i: 1 }),
    electionDate: ISODate("2023-05-05T06:23:41.000Z"),
    configVersion: 225221,
    configTerm: -1,
    self: true,
    lastHeartbeatMessage: ''
  }
]

์šฐํšŒํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ reconfig์˜ force ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. ์ฝ”๋“œ๋ฅผ ๋Œ€๋žต์ ์œผ๋กœ ์„ค๋ช…ํ•˜์ž๋ฉด, rs.conf() ๋ช…๋ น์œผ๋กœ ์‚ด์•„์žˆ๋Š” ๋ฉค๋ฒ„์˜ ๋ฐฐ์—ด ์œ„์น˜๋ฅผ ํ™•์ธํ•˜๊ณ ... members ๋ฐฐ์—ด์— ์‚ด์•„ ์žˆ๋Š” seconday ๋ฉค๋ฒ„ ํ•˜๋‚˜๋ฅผ ๋„ฃ๊ณ  ๊ฐ•์ œ๋กœ Replica Set์„ ์žฌ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์ด๋ ‡๊ฒŒ secondary ๋ฉค๋ฒ„๋งŒ ์žˆ๋Š” ์ƒํƒœ์—์„œ๋„ ์ž„์‹œ์ ์œผ๋กœ standalone ํ˜•ํƒœ๋กœ ๋ฐฐํฌํ˜•ํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹จ, force๊ฐ€ ์•ˆ์ „ํ•œ ๋ช…๋ น์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ง€๊ธˆ์ฒ˜๋Ÿผ ์‘๊ธ‰์ฒ˜์น˜๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๋Œ“๊ธ€