ข้ามไปยังเนื้อหา

RDB Snapshots และ AOF

การ persistence แบบ RDB (Redis Database) บันทึก snapshot ของชุดข้อมูลทั้งหมด ณ เวลาหนึ่งลงในไฟล์ binary แบบกะทัดรัด เมื่อ startup Redis จะโหลดไฟล์นี้เพื่อกู้คืนสถานะ — ทำให้ RDB เป็นวิธีที่เร็วที่สุดในการกลับมาทำงานหลัง restart

คำสั่งด้วยตนเอง:

  • SAVE — บล็อกเซิร์ฟเวอร์ขณะเขียน snapshot หลีกเลี่ยงในการใช้งาน production
  • BGSAVE — fork child process เพื่อเขียน snapshot ในพื้นหลัง parent ยังคงรับ request ต่อไป

Threshold อัตโนมัติ ถูกกำหนดใน redis.conf โดยใช้ directive save รูปแบบคือ save <seconds> <changed-keys> — Redis ถ่าย snapshot หากมีการแก้ไข key อย่างน้อย <changed-keys> ภายใน <seconds> วินาทีที่ผ่านมา

save 3600 1
save 300 100
save 60 10000
dbfilename dump.rdb
dir /var/lib/redis

บรรทัด save สามบรรทัดข้างต้นหมายความว่า: snapshot ทุกชั่วโมงหาก key เปลี่ยนอย่างน้อย 1 รายการ, ทุก 5 นาทีหากเปลี่ยนอย่างน้อย 100 รายการ, หรือทุกนาทีหากเปลี่ยนอย่างน้อย 10,000 รายการ หากต้องการปิด snapshot อัตโนมัติทั้งหมด ให้ลบบรรทัด save ทั้งหมด หรือตั้งค่า save ""

ไฟล์ RDB มีขนาดกะทัดรัดและโหลดได้รวดเร็ว ข้อเสียคืออาจสูญเสียข้อมูลได้: ข้อมูลที่เขียนหลัง snapshot ล่าสุดจะหายไปหาก Redis crash ก่อน snapshot ถัดไป

AOF บันทึกคำสั่งเขียนทุกคำสั่งที่แก้ไขชุดข้อมูล โดย append ลงในไฟล์ในรูปแบบ text เดียวกับที่ Redis ใช้ส่งข้อมูล เมื่อ restart Redis จะเล่น file ซ้ำตั้งแต่ต้นจนจบเพื่อสร้างชุดข้อมูลขึ้นใหม่

เปิดใช้ AOF ใน redis.conf:

appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

ตัวเลือก appendfsync ควบคุมความถี่ที่ Redis เรียก fsync() เพื่อ flush OS buffer ลงดิสก์:

  • always — flush หลังทุกคำสั่ง durability สูงสุด throughput ต่ำสุด
  • everysec — flush ทุกวินาที สูญเสียข้อมูลได้มากที่สุดหนึ่งวินาที แนะนำสำหรับ workload ส่วนใหญ่
  • no — ให้ OS ตัดสินใจเมื่อจะ flush เร็วที่สุด durability ต่ำสุด

เมื่อเวลาผ่านไป ไฟล์ AOF จะขยายใหญ่ขึ้น Redis จะบีบอัดด้วย BGREWRITEAOF ซึ่ง fork child เพื่อเขียน log ใหม่โดยใช้ชุดคำสั่งขั้นต่ำที่จำเป็นในการสร้างชุดข้อมูลปัจจุบันขึ้นใหม่

127.0.0.1:6379> BGSAVE
Background saving started
127.0.0.1:6379> LASTSAVE
(integer) 1700000000
127.0.0.1:6379> CONFIG GET save
1) "save"
2) "3600 1 300 100 60 10000"
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started

LASTSAVE คืนค่า Unix timestamp ของ BGSAVE ที่สำเร็จล่าสุด ใช้เพื่อยืนยันว่า snapshot อัตโนมัติกำลังทำงานตามตารางเวลา

BGSAVE
LASTSAVE
CONFIG GET save
BGREWRITEAOF

Redis 4 แนะนำ hybrid mode และ Redis 7 ปรับปรุงให้ดียิ่งขึ้น ใน hybrid mode ไฟล์ AOF จะเริ่มต้นด้วย RDB snapshot ที่ฝังไว้ (สำหรับการโหลดที่รวดเร็ว) ตามด้วย incremental AOF command log (สำหรับ durability) คุณได้รับทั้งการ restart ที่เร็วของ RDB และการสูญเสียข้อมูลน้อยของ AOF ในไฟล์เดียว

เปิดใช้ hybrid mode ใน redis.conf:

aof-use-rdb-preamble yes

Hybrid mode เป็นค่าเริ่มต้นใน Redis 7 เมื่อเปิดใช้ทั้ง RDB และ AOF เป็น setup persistence ที่แนะนำสำหรับ production workload ส่วนใหญ่ที่ต้องการทั้งความเร็วและ durability

ตัวเลือกBenefitCost
RDB onlyไฟล์เล็ก กะทัดรัด restart เร็วที่สุดสูญเสียข้อมูลได้ตั้งแต่ snapshot ล่าสุด เหมาะกับ backup มากกว่า durability สูง
AOF onlyสูญเสียข้อมูลน้อยกว่า (สูงสุด ~1 วินาทีด้วย everysec)ไฟล์ใหญ่กว่า restart ช้ากว่าเพราะต้อง replay คำสั่งทั้งหมด
Hybrid mode (RDB + AOF, ค่าเริ่มต้นใน Redis 7)ได้ทั้ง restart เร็วของ RDB และ durability ของ AOF ในไฟล์เดียวใช้พื้นที่ดิสก์มากกว่าการเปิดใช้แบบเดียว และต้องดูแล config สองชุด
  • ใช้ RDB เพียงอย่างเดียวแล้วคาดหวัง durability สูง — RDB snapshot ตามรอบเวลา (save 60 10000 เป็นต้น) หมายความว่าข้อมูลที่เขียนหลัง snapshot ล่าสุดจะหายทั้งหมดถ้า Redis crash ก่อนถึงรอบถัดไป
  • รัน SAVE แบบ blocking ใน production แทน BGSAVESAVE บล็อกเซิร์ฟเวอร์จนกว่าจะเขียนไฟล์เสร็จ ทำให้ client อื่นค้างระหว่างนั้น ควรใช้ BGSAVE ที่ fork child process เพื่อเขียนในพื้นหลังเสมอ
  • ปล่อยให้ AOF โตโดยไม่ทำ BGREWRITEAOF — ไฟล์ AOF สะสมคำสั่งทุกคำสั่งไปเรื่อย ๆ หากไม่บีบอัดเป็นระยะ ไฟล์จะใหญ่ขึ้นจนกินพื้นที่ดิสก์และทำให้ restart ช้าลงมาก

💡 ตัวอย่างจากของจริง

Instagram — ใช้ RDB snapshot เป็นพื้นฐานของกลยุทธ์ backup สำหรับ Redis fleet ขนาดใหญ่ เพราะไฟล์ขนาดกะทัดรัดและกู้คืนได้เร็วเมื่อต้อง restore

Production workload ทั่วไปที่ต้องการทั้งความเร็วและ durability — ใช้ hybrid mode (ค่าเริ่มต้นใน Redis 7) เพื่อได้ประโยชน์ของทั้ง RDB และ AOF ในไฟล์เดียว โดยไม่ต้องเลือกอย่างใดอย่างหนึ่ง

คำสั่งใดที่เรียก RDB snapshot ในพื้นหลังโดยไม่บล็อกเซิร์ฟเวอร์?
การตั้งค่า `appendonly yes` ใน redis.conf เปิดใช้งานอะไร?
ชื่อไฟล์เริ่มต้นที่ Redis ใช้สำหรับ RDB snapshot คืออะไร?
ค่า `appendfsync` ใดที่ flush AOF buffer ลงดิสก์ทุกหนึ่งวินาที?