มาทำ Mongo Replica Set เพื่อชีวิตที่ปลอดภัยกันเถอะ

ต่อจากบทความเดิมในการทำ MongoDB แบบ Replica Set ได้ที่นี่

เกริ่นก่อนเริ่มนะครับเนื่องจากบทความเก่ามีการ ทำ MongoDB แบบ Replica Set แต่ไม่ได้อธิบายอะไรมากนักบทความนี้เลยจะมาขยายความและประโยชน์ในการทำ Replica Set ฉบับการทำใน MongoDB โดยผมจะทำให้อยู่คนละ Server กันเพื่ออีกตัวพังอีกตัวยังคงอยู่

โดยบทความนี้ขั้นสุดท้ายผมจะให้ Primary เป็นแค่ตัว Write ส่วน Secondary จะให้เป็นตัว Read

Replica Set ใน MongoDB คือกลุ่มของเซิร์ฟเวอร์ฐานข้อมูลที่ใช้คัดลอกข้อมูลกันและกันเพื่อเพิ่มความทนทานและความพร้อมในการให้บริการของระบบฐานข้อมูล

ยกตัวอย่างเช่น:

  • ตั้งเซิร์ฟเวอร์ฐานข้อมูลมา 3 เครื่อง: เครื่อง A, B, และ C
  • เครื่อง A ถูกตั้งเป็น Primary, และเครื่อง B กับ C ถูกตั้งเป็น Secondary

หลักการทำงานคือ:

  • เราจะเขียนข้อมูลลงใน Primary เท่านั้น ซึ่งก็คือเครื่อง A
  • เครื่อง A จะมีหน้าที่คัดลอก (replicate) ข้อมูลไปยังเครื่อง B และ C ที่เป็น Secondary
  • ทำให้เครื่อง A, B, และ C มีข้อมูลที่เท่ากัน

ประโยชน์หลัก:

  • เมื่อเซิร์ฟเวอร์ A (Primary) ล่ม, เราสามารถปรับเครื่อง B หรือ C ให้เป็น Primary แทน
  • ลดปัญหาการ Downtime ได้มาก เนื่องจากเรามีสำเนาของข้อมูลในเครื่อง Secondary

นอกจากนี้:

  • เราสามารถใช้เครื่อง A สำหรับการเขียนข้อมูล (Write Database)
  • และใช้เครื่อง B และ C สำหรับการอ่านข้อมูล (Read Database)
  • ซึ่งจะช่วยลดปัญหาคอขวดและเพิ่มประสิทธิภาพในการอ่านและเขียนข้อมูล

สิ่งที่ต้องเตรียม

  • เครื่อง Server 2 เครื่อง
  • เปิด Port ให้พร้อมสำหรับ Mongodb
  • ลง Docker และ Docker-compose ให้เรียบร้อย

มาทำกันเลยดีกว่าครับเพื่อให้ได้เห็นภาพที่ชัดยิ่งขึ้น

ผมจะเอา Docker-compose ที่เหมือนกันเปะไปไว้คนละ Server เพื่อสร้าง Mongo DB 2ตัว เกริ่นหัวเรื่องผม ยกตัวอย่าง A B และ C แต่ทำจริงผมจะทำแค่ 2 เครื่องคือ A และ B

และผมจะเตรียม File init-mongo.js เพื่อให้สิท rootuser ให้เรียบร้อยตั้งแต่เริ่ม Run Docker

openssl rand -base64 756 >./mongo-keyfile
chmod 400 ./mongo-keyfile

จากนั้นผมจะ random เพื่อสร้าง mongo-keyfile ขึ้นมา
*หมายเหตุ random มาแค่เครื่องเดียวนะ แล้ว Copy จากเครื่องที่จะให้เป็น Primary ไปใส่ที่เครื่อง Secondary ถ้า Key ไม่ตรงกันมันจะคุยกันไม่ได้เป็นเรื่องของความ Secuerity

docker exec -it id sh

ทำการ SH เข้าไปใน Container mongodb

mongosh "mongodb://rootuser:rootpass@localhost:27017/admin"

คำสั่งนี้เริ่มต้นการเชื่อมต่อกับ MongoDB ที่ทำงานอยู่บน localhost

จากนั้นก็ทำการ Initiate โดย Add Primary และ Secondary
*หมายเหตุ ขั้นนี้ทำเฉพาะเครื่อง Primary นะ เครื่อง Secondary Run Docker ขึ้นเป็นอันจบไปแล้ว

rs.add("SecondaryInstanceIP:27017")

การใช้ rs.add() เพื่อเพิ่ม Secondary ภายหลักก็ได้เมื่อเราอยากมีเครื่องเพื่อสำรองข้อมูลเพิ่มเราก็สามารถ Add ไปได้ที่ Server ที่เป็น Primary ได้เลย

cfg = rs.conf()
cfg.members[0].priority = 3
cfg.members[1].priority = 2
cfg.members[1].priority = 1
rs.reconfig(cfg, {force: true});

ต้อง Set Priority ให้มันด้วยไม่งั้นมันจะไม่ปรับ primary ให้อัตโนมัติ

rs.status()

{
“optime” : { “ts”: Timestamp({ “t”: 1715845662, “i”: 1 }), “t”: Long(“2”) },
“optimeDate” : ISODate(“2024–05–16T07:47:42.000Z”),
“lastAppliedWallTime” : ISODate(“2024–05–16T07:47:42.716Z”),
“lastDurableWallTime” : ISODate(“2024–05–16T07:47:42.716Z”),

“syncSourceHost” : “PrimaryInstanceIP:27017”,
}

จากนั้นลองเช็ค Status ดูให้ดูที่ตัว lastAppliedWallTime และ lastDurableWallTime ถ้าทั้งของ Primary และ Secondary เท่ากันแล้วแสดงว่า Sync ข้อมูลหากันหมดแล้ว

mongodb://rootuser:rootpass@PrimaryInstanceIP:27017,SecondaryInstanceIP:27017/?replicaSet=rs0&readPreference=secondaryPreferred

ผมทำการ Config URL Mongo แบบนี้เพื่อที่จะให้:

  • การเขียน (write) ทั้งหมดจะถูกส่งไปยัง Primary (PrimaryInstanceIP:27017)
  • การอ่าน (read) จะพยายามอ่านจาก Secondary (SecondaryInstanceIP:27017) ก่อน แต่ถ้า Secondary ไม่พร้อมใช้งานก็จะอ่านจาก Primary
  • ถ้า Primary ล่มจะเปลี่ยนตัว Secondary มาเป็น Primary แทนเลย

เป็นยังไงกันบ้างครับหลังอ่านจนจบมาถึงตรงนี้ เท่านี้เราก็จะได้ MongoDB ที่ได้ทั้งความเสถียร และ การสำรองข้อมูลแบบ Realtime ได้ทั้งความ Security และ ลดปัญหาการ Downtime เมื่อเกิดปัญหา และยังสามารถเลือกเครื่อง Server ให้ MongoDB แต่ละตัวด้วยมือตัวเองอีกด้วย

--

--

Responses (1)