
บทนำ
การล็อคแบบกระจายฟังดูเรียบง่ายจนกว่าคุณจะพึ่งพาการล็อคเหล่านี้ในการใช้งานจริง
กระบวนการหนึ่งต้องการการเข้าถึงทรัพยากรแต่เพียงผู้เดียว เซิร์ฟเวอร์หลายเครื่องกำลังทำงานอยู่ เรดิสนั่งอยู่ตรงกลาง แนวคิดนี้ให้ความรู้สึกตรงไปตรงมา:ล็อค Redis แล้วเดินหน้าต่อไป
ดูเหมือนว่าวิธีนี้จะใช้ได้สักระยะหนึ่ง จากนั้นกระบวนการขัดข้อง ความล่าช้าของเครือข่ายเกิดขึ้น หรือเวลาแฝงพุ่งสูงขึ้น ทันใดนั้น สองกระบวนการก็อ้างสิทธิ์การล็อคเดียวกัน ไม่มีกระบวนการใดเป็นเจ้าของ หรือการล็อคไม่เคยถูกปลดออก
ปัญหาการล็อก Redis ส่วนใหญ่ไม่ได้เกิดจากตัว Redis เอง สิ่งเหล่านี้เกิดขึ้นเนื่องจากการล็อคแบบกระจายมักถูกเข้าใจผิด Redis เป็นเครื่องมือสำหรับการประสานงาน ไม่ใช่การรับประกันถึงความพิเศษเฉพาะตัวที่สมบูรณ์แบบ
การล็อคแบบกระจายจริงๆ คืออะไร
การล็อคแบบกระจายไม่เหมือนกับ mutex ในหน่วยความจำ ไม่ได้รับประกันโดยสมบูรณ์ และไม่สามารถขจัดความล้มเหลวได้
ล็อคแบบกระจายเป็นกลไกการประสานงานที่ทำงานในสภาพแวดล้อมที่ไม่น่าเชื่อถือ เครือข่ายล้มเหลว กระบวนการขัดข้อง และนาฬิกาเคลื่อนไป กลยุทธ์การล็อคใด ๆ ที่ถือว่าพฤติกรรมสมบูรณ์แบบจะพังในที่สุด
ล็อค Redis เป็นระบบล็อคที่ดีที่สุด เมื่อออกแบบอย่างถูกต้องจะมีประสิทธิภาพอย่างมาก เมื่อนำไปใช้แบบไม่เป็นทางการ จะทำให้เกิดสภาวะการแข่งขันที่ละเอียดอ่อนและข้อมูลเสียหาย
ขั้นตอนแรกในการใช้ Redis lock อย่างปลอดภัยคือการปรับความคาดหวัง
เมื่อ Redis Lock สมเหตุสมผล
การล็อคแบบกระจาย Redis มีความเหมาะสมเมื่อ:
-
คุณต้องป้องกันการดำเนินการส่วนสำคัญพร้อมกัน
-
งานต้องได้รับการประสานงานข้ามเซิร์ฟเวอร์หลายเครื่อง
-
การดำเนินการมีอายุสั้น
-
การลองใหม่เป็นที่ยอมรับ
กรณีการใช้งานทั่วไป ได้แก่ การขจัดความซ้ำซ้อนของงาน การประสานงานงานตามกำหนดเวลา การสร้างแคชใหม่ และการป้องกันการประมวลผลซ้ำซ้อน
การล็อก Redis ไม่เหมาะอย่างยิ่งสำหรับธุรกรรมทางธุรกิจที่ใช้เวลานาน เวิร์กโฟลว์ที่สำคัญที่ต้องเผชิญต่อผู้ใช้ หรือการดำเนินการที่ไม่สามารถลองใหม่ได้อย่างปลอดภัย หากไม่ยอมรับการลองใหม่ การล็อก Redis ถือเป็นเครื่องมือที่ไม่ถูกต้อง
ระบบล็อคแบบปลอดภัยเพียงรุ่นเดียวใน Redis
วิธีดั้งเดิมในการล็อก Redis ที่ปลอดภัยที่สุดคือคำสั่งอะตอมมิกคำสั่งเดียว:
ตั้งค่าคีย์ NX EX ttl
คำสั่งนี้สร้างการล็อคเฉพาะในกรณีที่ยังไม่มีอยู่ กำหนดค่าเจ้าของที่ไม่ซ้ำกัน และตั้งค่า TTL เพื่อให้การล็อคหมดอายุโดยอัตโนมัติ
แนวทางอื่นใดจะแนะนำสภาพการแข่งขัน การใช้ SETNX โดยไม่มี TTL หรือการตั้งค่าการหมดอายุในขั้นตอนที่แยกจากกันจะทำให้ระบบหยุดทำงานภายใต้ความล้มเหลว TTL เป็นสิ่งจำเป็นและปกป้องระบบเมื่อกระบวนการขัดข้องโดยไม่คาดคิด
เหตุใดจึงต้องล็อค TTL
หากไม่มี TTL ล็อค Redis จะคงอยู่ตลอดไป หากกระบวนการล้มเหลวในขณะที่ล็อคไว้ ระบบจะหยุดทำงานอย่างเงียบ ๆ
TTL ทำให้ล็อคสามารถรักษาตัวเองได้ เมื่อเกิดความล้มเหลว การล็อคจะหมดอายุในที่สุด และอนุญาตให้ดำเนินการต่อได้ ซึ่งอาจส่งผลให้เกิดการทับซ้อนกันในช่วงสั้นๆ แต่การแลกเปลี่ยนนั้นเกิดขึ้นโดยเจตนา
ล็อคที่ไม่มีวันหมดอายุนั้นอันตรายมากกว่าการล็อคเลย
ล็อคการเป็นเจ้าของและการปล่อยอย่างปลอดภัย
การล็อค Redis จะต้องปลดล็อคโดยกระบวนการที่ได้มาเท่านั้น นี่คือสาเหตุที่ค่าล็อคควรเป็นตัวระบุที่ไม่ซ้ำกัน ไม่ใช่สตริงคงที่
การปลดล็อคต้องมีการยืนยันความเป็นเจ้าของ แนวทางที่ปลอดภัยคือการใช้สคริปต์ Lua ที่ตรวจสอบค่าที่เก็บไว้และลบการล็อคเฉพาะเมื่อตรงกับเจ้าของที่คาดหวังเท่านั้น
วิธีนี้จะช่วยป้องกันสภาวะการแข่งขันที่การล็อคหมดอายุ ถูกได้มาโดยกระบวนการอื่น และจากนั้นเจ้าของเดิมก็ลบออกโดยไม่ตั้งใจ
การเลือกระยะเวลาล็อคแบบปลอดภัย
การล็อก TTL ต้องเกินเวลาดำเนินการสูงสุดที่คาดไว้ของการดำเนินการที่ได้รับการป้องกัน การใช้เวลาดำเนินการโดยเฉลี่ยไม่เพียงพอ
ถ้าการล็อคหมดอายุในขณะที่งานยังคงรันอยู่ กระบวนการอื่นอาจได้รับมันและทำงานเดียวกันไปพร้อมๆ กัน สิ่งนี้อาจทำให้เกิดการทำซ้ำหรือความเสียหายได้
ในเวลาเดียวกัน TTL ที่ยาวเกินไปจะชะลอการกู้คืนเมื่อมีสิ่งผิดปกติเกิดขึ้น ระยะเวลาการล็อคคือความสมดุลที่พัฒนาไปตามการเปลี่ยนแปลงของระบบ
การทำให้งานที่ถูกล็อกมีขนาดเล็กและมีขอบเขตเป็นแนวทางที่ปลอดภัยที่สุด
ล็อคส่วนขยายและฮาร์ทบีท
การดำเนินการบางอย่างใช้เวลานานกว่าที่คาดไว้ สามารถขยายการล็อคโดยการรีเฟรช TTL เป็นระยะๆ ได้ แต่จะเพิ่มความซับซ้อนและโหมดความล้มเหลวใหม่
มีเพียงเจ้าของล็อคเท่านั้นที่ควรได้รับอนุญาตให้ขยาย TTL และส่วนขยายจะต้องหยุดทันทีหากสูญเสียความเป็นเจ้าของ
ในหลายกรณี การออกแบบงานใหม่เป็นชิ้นเล็กๆ จะปลอดภัยกว่าการใช้ตรรกะส่วนขยายการล็อค
การอภิปราย Redlock
Redlock เป็นอัลกอริทึมที่ใช้อินสแตนซ์ Redis หลายอินสแตนซ์เพื่อปรับปรุงความปลอดภัยของล็อค นอกจากนี้ยังมีข้อขัดแย้งและซับซ้อนในการปฏิบัติงาน
สำหรับระบบส่วนใหญ่ Redlock นำเสนอความซับซ้อนมากกว่าประโยชน์ ขึ้นอยู่กับสมมติฐานด้านเวลาที่รับประกันได้ยากในสภาพแวดล้อมจริง
หากจำเป็นต้องมีการรับประกันระดับ Redlock Redis อาจไม่ใช่เครื่องมือที่เหมาะสม ฐานข้อมูลที่มีการล็อกธุรกรรมหรือระบบประสานงานเฉพาะทางอาจเหมาะสมกว่า
สำหรับกรณีการใช้งาน Redis ส่วนใหญ่ อินสแตนซ์ Redis เดี่ยวที่มีการล็อกแบบ TTL ที่เหมาะสมก็เพียงพอแล้ว
การล็อคไม่ใช่การทำธุรกรรม
การล็อค Redis ไม่ทำให้การดำเนินการเป็นธุรกรรม พวกเขาไม่ได้ให้การย้อนกลับอัตโนมัติหรือรับประกันความสม่ำเสมอเมื่อเกิดความล้มเหลวระหว่างการทำงาน
ล็อคช่วยลดการทำงานพร้อมกัน พวกเขาไม่ได้ขจัดความล้มเหลว ส่วนที่สำคัญควรได้รับการออกแบบให้เป็นแบบเดิม เพื่อให้การดำเนินการซ้ำๆ ไม่ก่อให้เกิดอันตราย
หลักการออกแบบนี้ช่วยลดความเสี่ยงของข้อบกพร่องที่เกี่ยวข้องกับการล็อคได้อย่างมาก
จะเกิดอะไรขึ้นเมื่อ Redis ลงไป
เมื่อ Redis หยุดทำงานหรือรีสตาร์ท การล็อคทั้งหมดจะหายไป นี่คือลักษณะการทำงานที่คาดหวัง
เมื่อ Redis กลับมาออนไลน์ กระบวนการต่างๆ อาจได้รับการล็อคพร้อมกันและเริ่มทำงาน ระบบจะต้องยอมรับความเป็นไปได้นี้
หากการสูญเสียการล็อคระหว่างการรีสตาร์ท Redis ทำให้เกิดความเสียหาย การออกแบบการล็อคจะไม่ปลอดภัยและจำเป็นต้องได้รับการพิจารณาใหม่
การตรวจสอบล็อคในการผลิต
ล็อค Redis ไม่ควรมองไม่เห็น ทีมควรตรวจสอบจำนวนการล็อคที่มีอยู่ ระยะเวลาที่ใช้ และความถี่ในการรับการล็อคที่ล้มเหลว
ระบบล็อคที่มีอายุการใช้งานยาวนานผิดปกติบ่งชี้ว่ากระบวนการหยุดทำงาน ความล้มเหลวในการรับข้อมูลบ่อยครั้งทำให้เกิดความขัดแย้งหรือการออกแบบล็อคที่ไม่ถูกต้อง
การมองเห็นเป็นสิ่งจำเป็นสำหรับการทำงานที่ปลอดภัย
รูปแบบการป้องกัน Redis Lock ทั่วไป
ข้อผิดพลาดทั่วไป ได้แก่ การใช้ SETNX โดยไม่มี TTL การใช้ค่าคงที่สำหรับการเป็นเจ้าของล็อค การลบล็อคแบบสุ่มสี่สุ่มห้า การล็อคล็อคไว้สำหรับงานที่ใช้เวลานาน และสมมติว่าล็อครับประกันความถูกต้อง
รูปแบบการต่อต้านเหล่านี้ปรากฏบ่อยครั้งในการหยุดทำงานของการผลิตในโลกแห่งความเป็นจริง
รายการตรวจสอบการล็อคที่ใช้งานได้จริง
การใช้งานการล็อก Redis ที่ปลอดภัยประกอบด้วย:
-
ล็อคกุญแจด้วย TTLs
-
ค่าความเป็นเจ้าของล็อคเฉพาะ
-
การยืนยันความเป็นเจ้าของเมื่อเผยแพร่
-
ส่วนสำคัญที่มีอายุสั้น
-
การดำเนินการที่ไม่มีประสิทธิภาพ
-
เส้นทางความล้มเหลวที่ทดสอบแล้ว
หากขาดหายไป ควรพิจารณาการออกแบบตัวล็อคใหม่
แบบจำลองทางจิตที่ดีต่อสุขภาพสำหรับ Redis Locks
ระบบล็อค Redis คือเข็มขัดนิรภัย ไม่ใช่ถุงลมนิรภัย ลดความเสียหายแต่ไม่ได้ป้องกันอุบัติเหตุทั้งหมด
ใช้อย่างระมัดระวังเพื่อลดความซับซ้อนของการประสานงานในระบบแบบกระจาย หากใช้แบบไม่เป็นทางการจะทำให้เกิดข้อบกพร่องที่ละเอียดอ่อนและต่อเนื่อง
สรุป
การล็อคแบบกระจายทำได้ยากเนื่องจากความล้มเหลวเป็นสิ่งที่หลีกเลี่ยงไม่ได้ Redis มีกลไกการล็อคที่รวดเร็ว เรียบง่าย และใช้งานได้จริง ไม่ใช่กลไกที่สมบูรณ์แบบ
ออกแบบเพื่อป้องกันความล้มเหลว ล็อคให้สั้น ใช้ TTL อย่างสม่ำเสมอ และรับรองว่าการดำเนินการจะปลอดภัยในการลองอีกครั้ง เมื่อใช้อย่างถูกต้อง ระบบล็อคแบบกระจาย Redis จะเป็นเครื่องมือที่เชื่อถือได้และมีประสิทธิภาพในระบบการผลิต