Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> ฐานข้อมูล

การทำงานของ PUBSUB และรายการบล็อกที่เชื่อถือได้ในการปรับใช้ HA Redis

การทำงานของ PUBSUB และรายการบล็อกที่เชื่อถือได้ในการปรับใช้ HA Redis

โซลูชัน Redis ที่ซ้ำซ้อนมาตรฐานคือการรันการจำลองแบบ master/slave ด้วย Sentinel ที่จัดการการเฟลโอเวอร์ ซึ่งคาดว่าจะตามมาด้วย a) การสนับสนุนไคลเอ็นต์และการใช้ Sentinel เพื่อค้นหาต้นแบบปัจจุบัน หรือ b) พร็อกซี TCP ที่ด้านหน้าพ็อด Redis ซึ่งจัดการโดย Sentinel เพื่อชี้ไปที่ต้นแบบ แบบแรกคือวิธีการออกแบบ Redis Sentinel และแบบหลังเป็นเทรนด์ที่กำลังเติบโต – และวิธีการกำหนดค่า ObjectRocket Redis

ผลกระทบของการเฟลโอเวอร์ต่อคำสั่งใน Redis

สำหรับการดำเนินการ Redis ส่วนใหญ่ การทำงานนี้เป็นไปตามที่คาดไว้ เมื่อเกิดข้อผิดพลาด โค้ดไคลเอ็นต์คาดว่าจะตรวจพบว่าการเชื่อมต่อล้มเหลว และ a) ค้นหาต้นแบบปัจจุบันและเชื่อมต่อใหม่ หรือ b) พยายามเชื่อมต่อใหม่ตามสถานการณ์ที่กล่าวถึงข้างต้น สถานการณ์ตามพร็อกซีนั้นเหมือนกันกับการรีสตาร์ทเซิร์ฟเวอร์ Redis ดังนั้นสิ่งนี้จึงใช้ได้กับกรณีที่คุณมี Redis อินสแตนซ์เดียวที่สามารถรีสตาร์ทได้

อย่างไรก็ตาม คำสั่ง Redis จำนวนเล็กน้อยเป็นการบล็อกระยะยาวหรือไม่ใช่แบบปรมาณู คำสั่งสมัครสมาชิกและ psubscribe ของ PUBSUB นั้นไม่ใช่แบบอะตอมมิก โดยคำสั่งจะลงทะเบียนขอให้มีข้อความใด ๆ ที่ส่งไปยังช่องที่กำหนดที่ส่งไปด้วยเช่นกัน แต่ข้อมูลจริงอาจมาถึงได้ช้ากว่ามาก เช่น หลังจากเผยแพร่ คำสั่ง BL* เป็นคำสั่งระยะยาวและแบบสองเฟสซึ่งเหมือนกับคำสั่งสมัครรับข้อมูลที่พวกเขาจะบล็อกและไม่ส่งคืนจนกว่ารายการจะพร้อมใช้งานในรายการที่จะลบออก

ความคล้ายคลึงกันที่สำคัญระหว่างคำสั่งเหล่านี้คือการออกคำสั่งและรูปแบบการลงทะเบียนเสร็จสิ้นบนเซิร์ฟเวอร์ แต่ข้อมูลสามารถมาในภายหลัง ระหว่างคำสั่งที่ออกและเซิร์ฟเวอร์ที่มีข้อมูลเพื่อตอบกลับด้วยความล้มเหลวและการรีสตาร์ทสามารถเกิดขึ้นได้ ในกรณีของการรีสตาร์ทหรือเฟลโอเวอร์ “การลงทะเบียน” จะไม่อยู่บนเซิร์ฟเวอร์อีกต่อไป สิ่งนี้นำเราไปสู่คำถามว่าเกิดอะไรขึ้นกับคำสั่งเหล่านี้ในสถานการณ์เหล่านี้

ก่อนที่จะเจาะลึกรายละเอียดเหล่านั้น มีแง่มุมอื่นที่ต้องนำมาพิจารณา เนื่องจากจะมีผลในระหว่างการทดสอบและมีผลกระทบอย่างมากต่อผลลัพธ์และวิธีการเขียนโค้ดสำหรับสถานการณ์ความล้มเหลว ที่จริงแล้วมีข้อผิดพลาดสองประเภท มีความล้มเหลวที่เราส่วนใหญ่พิจารณา - การสูญเสียต้นแบบ ในการเฟลโอเวอร์ประเภทนี้ ต้นแบบจะไม่ตอบสนอง ฉันเรียกสิ่งนี้ว่า คลาสที่สองของเฟลโอเวอร์ที่ฉันเรียกว่า "เฟลโอเวอร์ที่เริ่มต้น"

เฟลโอเวอร์ที่เริ่มต้นจะเกิดขึ้นเมื่อผู้ดูแลระบบส่งคำสั่งเฟลโอเวอร์ของ Sentinel ไปยัง Sentinel ซึ่งจะกำหนดค่าพ็อดใหม่ เลื่อนระดับมาสเตอร์แล้วลดระดับมาสเตอร์ดั้งเดิม บนพื้นผิวทั้งสองสถานการณ์นี้ดูเหมือนจะเหมือนกัน ในกรณีของคำสั่ง Redis ส่วนใหญ่ คำสั่งเหล่านี้สามารถปฏิบัติได้เหมือนกัน อย่างไรก็ตาม ในกรณีของคำสั่งบล็อกยาวของเรา พวกเขาจะต้องเข้าใจในบริบทของตนเอง

ตัวสร้างความแตกต่างของฟังก์ชันหลักระหว่างคลาสเฟลโอเวอร์ทั้งสองนี้คือลำดับของเหตุการณ์ เมื่อเกิดข้อผิดพลาดที่ทริกเกอร์ อาจเป็นเพราะต้นแบบไม่ตอบสนอง ด้วยเหตุนี้จึงไม่มีการเพิ่มหรือแก้ไขข้อมูล และไม่มีข้อความที่เผยแพร่บนต้นแบบ ในเฟลโอเวอร์ที่เริ่มต้น จะมีหน้าต่างสั้นๆ ที่มีมาสเตอร์สองตัว

เทคนิคและสถานการณ์ที่กล่าวถึงในที่นี้จะอธิบายโดยทั่วไปและสาธิตโดยใช้ไลบรารี Python Redis "redis-py" แต่นำไปใช้กับไลบรารีของไคลเอ็นต์ใดๆ ด้วยพื้นหลังในมือ ให้เราดูว่าสิ่งนี้ส่งผลต่อการใช้คำสั่งแบบบล็อกยาวอย่างไร ก่อนอื่นเรามาดู PUBSUB กันก่อน

PUBSUB

Redis PUBSUB ประกอบด้วยคำสั่งสามคำสั่ง:PUBLISH, SUBSCRIBE และ PSUBSCRIBE คำสั่งแรกใช้เพื่อส่งข้อความในขณะที่สองคำสั่งหลังใช้เพื่อลงทะเบียนและรับข้อความที่เผยแพร่ผ่านคำสั่ง PUBLISH ขั้นแรก ให้เราตรวจสอบสิ่งที่เกิดขึ้นในคำสั่ง PUBLISH

เมื่อคุณดำเนินการเผยแพร่ มันจะเผยแพร่ข้อความไปยังช่องทางที่กำหนดทันทีและส่งคืนจำนวนไคลเอนต์ที่ได้รับ สถานการณ์ความล้มเหลวนำสิ่งนี้มาเกี่ยวข้องในทางใด พิจารณากรณีของการเฟลโอเวอร์ ลูกค้าจะต้องเชื่อมต่อใหม่เมื่อการเชื่อมต่อ TCP หายไป หากพูดคุยกับพร็อกซี่ จะทำการเชื่อมต่อใหม่โดยตรงและรับเซิร์ฟเวอร์อื่น หากทำการค้นหา Sentinel จะใช้เวลานานขึ้นเล็กน้อยและยังคงเชื่อมต่อกับเซิร์ฟเวอร์อื่น ที่ปัญหาอยู่ในช่วงเวลา หากผู้เผยแพร่เชื่อมต่อกับเซิร์ฟเวอร์ใหม่ก่อนที่สมาชิกจะทำ ข้อความจะหายไป – สูญหาย แต่สิ่งนั้นจะเกิดขึ้นได้ไหม? เพื่อให้เข้าใจว่าเราดูที่คำสั่ง SUBSCRIBE

เมื่อรหัสของคุณออกคำสั่งสมัคร เซิร์ฟเวอร์จะลงทะเบียนในโครงสร้างข้อมูลในหน่วยความจำซึ่งการเชื่อมต่อนั้นควรได้รับข้อความในช่องที่สมัครรับข้อมูล ข้อมูลนี้ไม่ได้เผยแพร่ไปยังทาส ดังนั้นเมื่อเกิดความล้มเหลวและไคลเอ็นต์เชื่อมต่อใหม่ จะต้องออกคำสั่งสมัครใหม่อีกครั้ง มิฉะนั้นเซิร์ฟเวอร์ใหม่จะไม่ทราบว่าการเชื่อมต่อเฉพาะนั้นจำเป็นต้องได้รับข้อความบางอย่าง ตอนนี้เรามีศักยภาพที่ชัดเจนสำหรับผู้สมัครสมาชิกเพื่อเชื่อมต่อกับต้นแบบใหม่หลังจากผู้เผยแพร่ ขณะนี้มีเงื่อนไขสำหรับการสูญเสียข้อความ แล้วจะลดหรือป้องกันได้อย่างไร? มีตัวเลือกน้อย

ขั้นแรก ผู้เผยแพร่สามารถใช้ประโยชน์จากข้อเท็จจริงที่ว่า PUBLISH ส่งคืนจำนวนลูกค้าที่ได้รับ หากไคลเอนต์ได้รับเป็นศูนย์ ผู้เผยแพร่สามารถลองอีกครั้ง สำหรับระบบที่มีจำนวนสมาชิกคงที่หรือ "สมาชิกอย่างน้อยหนึ่งราย" ก็เพียงพอแล้ว การทำเช่นนี้จะช่วยป้องกันไม่ให้ข้อความสูญหาย สำหรับระบบที่ไม่ตรงตามเกณฑ์นี้ ก็มีตัวเลือกอื่น หากมีความแข็งแกร่งน้อยกว่า

ตัวเลือกที่สองคือการควบคุมหน้าต่างเชื่อมต่อใหม่ กฎทั่วไปในที่นี้คือ ให้ผู้เผยแพร่โฆษณาล่าช้าอย่างน้อยสามครั้งตราบเท่าที่ผู้สมัครสมาชิกล่าช้า สิ่งนี้จะให้โอกาสอย่างน้อยสามครั้งเพื่อให้สมาชิกเชื่อมต่อใหม่ก่อนเผยแพร่ข้อความ ตราบใดที่สมาชิกออนไลน์ก่อน ข้อความจะไม่เข้าไปในอีเธอร์ อย่างไรก็ตาม แม้จะแข็งแกร่งกว่าการไม่ควบคุม แต่ก็ยังมีความเป็นไปได้ที่ข้อความจะสูญหาย

ตัวเลือกที่สามที่ฉันจะนำเสนอเพื่อลดสภาวะการแข่งขันนี้คือการสร้างกลไกการล็อค นี่เป็นเส้นทางที่ซับซ้อนที่สุดเนื่องจากต้องมีการสร้างหรือใช้กลไกที่ป้องกันไม่ให้ผู้เผยแพร่เผยแพร่จนกว่าไคลเอ็นต์จะเชื่อมต่อ กระบวนการพื้นฐานคือการมีสถานที่ที่ใช้ร่วมกันบางรูปแบบ (เช่นผ่าน Zookeeper ฐานข้อมูล กงสุล ฯลฯ) ซึ่งสมาชิกลงทะเบียนว่าพวกเขาพร้อมที่จะรับและสมาชิกจะตรวจสอบสมาชิกที่ถูกต้องและพร้อมก่อนที่จะเผยแพร่ข้อความ เพื่อให้โฆษณามีความซับซ้อนมากขึ้น สมาชิกจะต้อง "ยกเลิก" ตัวเองในกลไกนี้เมื่อสูญเสียการเชื่อมต่อ TCP

จะต้องมีการเรียกออกมาว่านี่คือทั้งหมดสำหรับกรณีเฟลโอเวอร์ที่ถูกทริกเกอร์ มันจะทำงานเพราะต้นแบบไม่ตอบสนองดังนั้นจึงไม่มีข้อความไปที่มัน ในสถานการณ์จำลองเมื่อเกิดข้อผิดพลาดที่เริ่มต้น ต้นแบบจะยังคงรับข้อความต่อไปจนกว่าจะไม่มีต้นแบบอีกต่อไปหรือถูกตัดการเชื่อมต่อ จากวิธีการข้างต้นไม่มีใครสามารถจับสถานการณ์นี้ได้อย่างถูกต้องและครบถ้วน

ในกรณีของเฟลโอเวอร์ที่เริ่มต้น (ซึ่งสามารถเกิดขึ้นได้ระหว่างการบำรุงรักษาระบบ) ผลการค้ำประกันที่ดีที่สุดของคุณคือการใช้ทั้งตัวเลือกแรกและตัวเลือกที่สอง และยอมรับว่าข้อความอาจสูญหายได้ จำนวนข้อความที่สูญหายขึ้นอยู่กับกำหนดการเผยแพร่ของคุณ หากคุณเผยแพร่ข้อความโดยเฉลี่ยทุกๆ สองสามนาที มีโอกาสเล็กน้อยที่คุณจะพบหน้าต่างการสูญเสีย ยิ่งช่วงการเผยแพร่มากเท่าไร ความเสี่ยงก็ยิ่งน้อยลงเท่านั้น ในทางกลับกัน หากคุณเผยแพร่ข้อความหลายแสนข้อความต่อวินาที คุณจะสูญเสียข้อความบางส่วนไปอย่างแน่นอน สำหรับสถานการณ์จำลองพร็อกซีที่ได้รับการจัดการ จะขึ้นอยู่กับความเร็วของการเฟลโอเวอร์ในพร็อกซีของคุณ สำหรับแพลตฟอร์ม Redis ของ ObjectRocket หน้าต่างนี้จะใช้เวลาไม่เกิน 1.5 วินาที

ดังนั้นแนวทางหนึ่งในช่วงเวลา ซึ่งล้มเหลวในขีดจำกัด คือให้สมาชิกพยายามเชื่อมต่อใหม่ในช่วงเวลา 1/3d ของช่วงการเผยแพร่ของคุณ ดังนั้น หากคุณเผยแพร่ข้อความหนึ่งครั้งต่อนาที ให้เขียนโค้ด/กำหนดค่าสมาชิกของคุณเพื่อเชื่อมต่อใหม่อย่างน้อยทุกๆ 20 วินาที และผู้เผยแพร่ของคุณทุกๆ นาทีหรือสองนาที เมื่อช่วงการเผยแพร่ใกล้ถึงเครื่องหมาย 3 วินาที การดำเนินการนี้จะยากขึ้นเนื่องจากกระบวนการเชื่อมต่อใหม่เมื่อเกิดข้อผิดพลาด (การค้นหา, TCP handshake, AUTH, SUBSCRIBE เป็นต้น) อาจใช้เวลาเพียงไม่กี่วินาที

BLPOP และผองเพื่อน

สิ่งนี้นำเราไปสู่คำถามว่าคำสั่งรายการบล็อกทำงานอย่างไรภายใต้เงื่อนไขเหล่านี้ ข่าวที่นี่ดีกว่าการเผยแพร่ ในกรณีนี้ เรากำลังแก้ไขโครงสร้างข้อมูลที่ทำซ้ำ นอกจากนี้ เนื่องจากสิ่งเหล่านี้เป็นการปรับเปลี่ยนโครงสร้างข้อมูล เราจึงไม่มีความเสี่ยงที่ข้อความจะสูญหายเนื่องจากลำดับการเชื่อมต่อใหม่ในระดับเดียวกัน หากผู้ผลิตเชื่อมต่อใหม่ก่อนผู้สมัครสมาชิก จะไม่มีการเปลี่ยนแปลงพฤติกรรมที่คาดไว้ ผู้ผลิตจะผลักดันรายการลงในรายการ (หรือ POP และ PUSH) และเมื่อผู้บริโภคเชื่อมต่อข้อมูลจะอยู่ที่นั่น มีข้อยกเว้นประการหนึ่ง

ในกรณีของเฟลโอเวอร์ที่เริ่มต้น เราต้องพิจารณาปัญหาหลักหลายรายการโดยย่อ ในช่วงเวลาสั้นๆ ตามลำดับมิลลิวินาที ต้นแบบดั้งเดิมระหว่างการเปลี่ยนระบบที่เริ่มต้นจะยังคงยอมรับการแก้ไขข้อมูล และเนื่องจากทาสได้รับการเลื่อนระดับให้เป็นต้นแบบแล้ว การแก้ไขเหล่านี้จะไม่ทำซ้ำ โปรดทราบว่าหน้าต่างนี้มีขนาดเล็กมาก ในการทดสอบเป็นลำดับของมิลลิวินาทีหลักเดียว แต่มันอยู่ที่นั่น เช่นเดียวกับการเผยแพร่ นี่เป็นเงื่อนไขพื้นฐานที่โอกาสของคุณ ตัวอย่างเช่น การออกคำสั่ง POP ให้กับผู้เชี่ยวชาญที่ล้าสมัยนั้นหายากแม้ว่าจะเพิ่มเป็นเงื่อนไขที่เป็นไปได้เมื่ออัตราของผู้ผลิตและผู้บริโภคของคุณที่ทำคำสั่งแก้ไขรายการถึงพันต่อวินาที

ตัวอย่างเช่น ในกรณีของผู้ปฏิบัติงานที่ทำ BRPOPLPUSH ผลลัพธ์จะเป็นเช่นว่ารายการที่กำลังย้ายจะ "กลับ" ในตำแหน่งเดิมหลังจากเกิดข้อผิดพลาด ในกรณีของ BLPOP ผลลัพธ์จะเหมือนกัน หลังจากเฟลโอเวอร์เสร็จสิ้น รายการจะดูเหมือนถูกจัดคิวใหม่ หากรายการของคุณเป็นงานที่ไม่มีประสิทธิภาพ เรื่องนี้ก็จะไม่เป็นปัญหา คุณควรใช้การเข้ารหัสป้องกันมากน้อยเพียงใดเพื่อพิจารณากรณีนี้ในกรณีที่งานที่ไม่ใช่งาน idempotent เป็นผลมาจากการกำหนดผลกระทบของงานที่กำลังดำเนินการหรือรายการที่มีการประมวลผลสองครั้งแฟคตอริ่งในความถี่ที่คุณทำการปรับเปลี่ยนและสิ่งนี้มีแนวโน้มที่จะประสบกับสิ่งนี้ สถานการณ์. นอกจากนี้ ควรสังเกตด้วยว่าเนื่องจากสิ่งนี้จะเกิดขึ้นเฉพาะในกรณีที่เกิดข้อผิดพลาดที่เริ่มต้น สิ่งนี้ควรเป็นสิ่งที่อยู่ภายใต้การควบคุมการปฏิบัติงาน และฉันขอแนะนำว่าเมื่อใดก็ตามที่เป็นไปได้ในการบำรุงรักษาควรทำในเวลาที่ระบบของคุณมีการใช้งานน้อยที่สุดเพื่อลดหรือกระทั่ง ขจัดความเป็นไปได้นี้

สำหรับกรณีเฟลโอเวอร์ที่ถูกทริกเกอร์ จะไม่มีการคาดการณ์ว่าข้อมูลจะสูญหาย การเฟลโอเวอร์ที่ถูกทริกเกอร์เกิดขึ้นเมื่อต้นแบบไม่ตอบสนอง ดังนั้นจึงไม่มีการปรับเปลี่ยนใดๆ กับต้นแบบ อย่างไรก็ตาม เช่นเดียวกับแต่ละสถานการณ์เหล่านี้ มีเรื่องของการจัดการการเชื่อมต่อ TCP ใหม่ ซึ่งจำเป็นในสถานการณ์ที่เฟลโอเวอร์ใดๆ

การเชื่อมต่อกับไคลเอ็นต์อีกครั้ง

ภายใต้สถานการณ์จำลองเมื่อเกิดข้อผิดพลาด ทั้งที่ทริกเกอร์หรือเริ่มต้น ไคลเอ็นต์จะต้องตรวจหาและเชื่อมต่อใหม่ ไม่ว่าจะหลังจากการค้นหา Sentinel หรือหน้าต่างสั้นๆ ไปยังที่อยู่เดียวกัน ในกรณีของ ObjectRocket Redis ซึ่งใช้ชั้นพร็อกซีที่มีการจัดการ ไคลเอนต์จะทำการเชื่อมต่อใหม่ กระบวนการเฟลโอเวอร์จริงอาจใช้เวลาถึงสองวินาทีจึงจะเสร็จสมบูรณ์ ดังนั้นรหัสลูกค้าควรคำนึงถึงสิ่งนี้ ตามหลักแล้ว ควรลองใหม่ทันทีเพื่อจัดการกับสัญญาณขัดข้องของเครือข่ายที่การเชื่อมต่อหลุดไปที่ไหนสักแห่งตามเส้นทาง อย่างไรก็ตาม สิ่งนี้ควรมาพร้อมกับอัลกอริธึมย้อนกลับที่มีการลองใหม่เพื่อพิจารณากรณีต่างๆ เช่น การรีสตาร์ทเซิร์ฟเวอร์ (เช่นที่เกิดขึ้นในการรีสตาร์ท Redis แบบสแตนด์อโลนหรือการรีสตาร์ทพร็อกซี)

เมื่อเชื่อมต่อใหม่ สมาชิกจะต้องสมัครใหม่อีกครั้ง เนื่องจากต้องมีการสร้างลิงก์ระหว่างช่องทางคำขอและการเชื่อมต่อ TCP ใหม่ เนื่องจากช่อง PUBSUB ของ Redis ถูกสร้างขึ้นเมื่อสมาชิกหรือผู้จัดพิมพ์พยายามเข้าถึง จึงไม่จำเป็นต้อง "สร้าง" ช่องใหม่

สิ่งนี้นำเราไปสู่วิธีการทำสิ่งนี้ คำตอบนั้นขึ้นอยู่กับไลบรารีของไคลเอ็นต์ที่ใช้งานและวิธีจัดการกับการยกเลิกการเชื่อมต่อ ในสถานการณ์ที่เหมาะสมที่สุด การเชื่อมต่อจะสามารถกำหนดค่าได้สำหรับการลองใหม่อัตโนมัติโดยมีการส่งคืนความล้มเหลวขั้นสุดท้ายหากตรงตามขอบเขต จนถึงตอนนี้ฉันได้ทดสอบห้องสมุดสองสามแห่งว่าพวกเขาจัดการกับสิ่งนี้อย่างไรและมันแตกต่างกันอย่างมาก ฉันจะพูดถึงสิ่งที่ค่อนข้างธรรมดา:redis-py

ข่าวดีช่วงแรกคือ redis-py จะพยายามลองอีกครั้งเมื่อการเชื่อมต่อหลุด น่าเสียดายที่ระบบจะลองใหม่ทันที ดังนั้นจึงเร็วเกินไปที่จะกู้คืนการเชื่อมต่อได้อย่างน่าเชื่อถือระหว่างเกิดข้อผิดพลาด นอกจากนี้ดูเหมือนว่าจะไม่มีวิธีกำหนดค่านี้ ด้วยเหตุนี้ รหัสของคุณจึงต้องตรวจจับ/ตรวจจับความพยายามเชื่อมต่อใหม่ที่ล้มเหลวและจัดการการเชื่อมต่อใหม่ด้วยตนเอง

ขั้นแรก ให้เราตรวจสอบมาตรฐานการบล็อก redis-py เผยแพร่และรหัสสมาชิก:

### Publisher example code
r.publish(channel,message)

### Subscriber example code
p = r.pubsub()
p.subscribe(channel)
for item in p.listen():
   # do stuff with message (item)

นี้ค่อนข้างตรงไปตรงมา อย่างไรก็ตาม เมื่อการลองใหม่ทันทีระหว่าง for-loop ของผู้สมัครสมาชิกล้มเหลว คุณจะได้รับข้อยกเว้น redis.ConnectionError บิตที่ยุ่งยากคือมันเกิดขึ้น "ภายใน" รายการสำหรับในบรรทัด p.listen() ดังนั้นเพื่อให้จับได้อย่างถูกต้อง คุณต้องตัดคำสั่งทั้งหมดสำหรับคำสั่งในบล็อกลอง/ยกเว้น นี่เป็นปัญหาที่ดีที่สุดและนำไปสู่ความซับซ้อนของโค้ดที่ไม่จำเป็น

เส้นทางอื่นให้ทำดังต่อไปนี้แทน

### Publisher example code
p = r.pubsub()
p.subscribe(channel)
while True:
    try:
        message = p.get_message()
    except redis.ConnectionError:
        # Do reconnection attempts here such as sleeping and retrying
        p = r.pubsub()
        p.subscribe(channel)
    if message:
        # do something with the message
    time.sleep(0.001)  # be nice to the system :)

ด้วยวิธีนี้ เราเรียก get_message() โดยตรง ซึ่งช่วยให้เราตรวจจับข้อยกเว้น ณ จุดนั้นและสร้างการเชื่อมต่อของอ็อบเจ็กต์ 'p' อีกครั้ง ระยะเวลาในการนอนหลับ (หากเลย) ขึ้นอยู่กับข้อกำหนดของรหัสของคุณ แน่นอนว่าหากสมาชิกของคุณคาดหวังว่าจะจัดการกับข้อความจำนวนหนึ่งและ for-loop ทำงานได้ดีขึ้น ก็จะยังคงใช้งานได้ สำหรับผู้จัดพิมพ์ โค้ดจะง่ายกว่า เนื่องจากโดยทั่วไปจะไม่รันบนตัววนซ้ำ

### Publisher example code
while True:
    try:
       rcvd = r.publish(channel,message)
       if rcvd >0:
          break
    except redis.ConnectionError:
       # handle reconnect attempts

ด้วยวิธีนี้ คุณจะควบคุมได้ว่าควรลองอีกครั้งเมื่อใด และบ่อยเพียงใด นี่เป็นสิ่งสำคัญในการจัดการเหตุการณ์ความล้มเหลวอย่างโปร่งใสอย่างเหมาะสม โปรดทราบว่านี่จะเป็นสิ่งเดียวกันที่จำเป็นหากรหัสกำลังใช้ Sentinel โดยตรง หรือแม้แต่เซิร์ฟเวอร์ Redis ที่เป็นปัญหาจะรีสตาร์ท ดังนั้นโค้ดที่เผยแพร่ทั้งหมดควรเป็นไปตามกลไกพื้นฐานนี้

สำหรับคำสั่งรายการบล็อก เช่น BLPOP ลำดับของการเชื่อมต่อไคลเอ็นต์ใหม่ไม่สำคัญอย่างยิ่งเนื่องจากข้อมูลยังคงอยู่ วิธีการลอง/ยกเว้นที่อธิบายข้างต้นจะต้องสร้างการเชื่อมต่อใหม่เมื่อการดำเนินการคำสั่งส่งผลให้เกิดข้อยกเว้น “redis.ConnectionError”

สำหรับ redis-py โดยเฉพาะกับแพลตฟอร์ม ObjectRocket Redis โดยใช้เทคนิคเหล่านี้โดยมีหน้าต่างลองใหม่เป็นเวลา 3 วินาที จะช่วยให้มั่นใจได้ว่าจะไม่มีข้อมูลสูญหายสำหรับกรณีเฟลโอเวอร์ที่ถูกทริกเกอร์ และข้อความที่อาจสูญหายประมาณ 1.5 วินาทีสำหรับผู้เผยแพร่ที่ไม่หยุดนิ่งระหว่างเฟลโอเวอร์ที่เริ่มต้น เช่น ระหว่างการปรับขนาดแนวตั้งของอินสแตนซ์

แม้ว่าตัวอย่างโค้ดจะเจาะจงสำหรับ redis-py แต่ควรใช้เทคนิคพื้นฐานกับโค้ดไคลเอ็นต์ใดๆ ที่ต้องจัดการการเชื่อมต่อเซิร์ฟเวอร์อีกครั้ง และใช้คำสั่ง PUBSUB หรือการดำเนินการรายการบล็อก ด้วยความรู้นี้ คุณสามารถใช้เทคนิคเหล่านี้เพื่อใช้ Redis pod ที่มีความพร้อมใช้งานสูงและรู้ว่าแอปพลิเคชันของคุณสามารถจัดการกับการเฟลโอเวอร์ได้โดยไม่ต้องปลุกทีมปฏิบัติการของคุณให้ตื่นกลางดึก