Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

RedisRaft: โมดูล Strong-Consistency สำหรับ Redis Clusters ที่ทนทานต่อข้อผิดพลาด

RedisRaft (อยู่ระหว่างการพัฒนา) เป็นโมดูลใหม่สำหรับ Redis open source ที่ทำให้เป็นไปได้ที่จะดำเนินการเซิร์ฟเวอร์ Redis หลายตัวเป็นคลัสเตอร์เดียวที่ทนทานต่อข้อผิดพลาด (fault-tolerant) และมีความสม่ำเสมอสูง (strongly consistent) ตามที่ชื่อบ่งชี้ มันพัฒนาจากอัลกอริทึมความเห็นชัด Raft consensus algorithm และไลบรารี C open-source ที่นำไปปฏิบัติ

RedisRaft นำตัวเลือกการปรับใช้ (deployment option) ที่มี strong-consistency พร้อม strict serialization มาสู่ Redis และระบบนิเวศ Redis โมดูลใหม่นี้ทำให้เป็นไปได้ที่จะใช้ Redis พร้อมกับไคลเอ็นต์ ไลบรารี และชนิดข้อมูลที่มีอยู่ของ Redis ในสถานการณ์ beyond-cache ที่ต้องการระดับความน่าเชื่อถือและความสม่ำเสมอสูง

จุดเริ่มต้นของ RedisRaft

RedisRaft เริ่มต้นเป็น "side project" แบบทดลองไม่ก่อนการเผยแพร่ Redis 5 มากี่นาน Redis module API ถูกนำเสนอใน Redis 4 โดยออกแบบมาเพื่อรองรับโมดูลที่นำชนิดข้อมูลและคำสั่งใหม่มาใช้ เราอยากสำรวจว่าเราสามารถดึง API ไปไกลแค่ไหน และใช้โมดูลขยาย Redis ในลักษณะที่รุนแรงกว่านี้ แต่เราก็อยากจบลงด้วยสิ่งที่มีประโยชน์—ตัวเลือกการปรับใช้ strong consistency สำหรับ Redis

คลัสเตอร์ RedisRaft เสนอระดับความสม่ำเสมอและความน่าเชื่อถือเท่ากับที่คาดหวังจาก data stores ที่น่าเชื่อถือและรู้จักกันดีอย่าง ZooKeeper หรือ Etcd ในโครงร่าง ใน RedisRaft:

  • การเขียนที่ได้รับการยืนยัน (Acknowledged writes) รับประกันว่าถูก commit และไม่สูญหายเลย
  • การอ่าน (Reads) จะคืนค่าการเขียนที่ commit ล่าสุดเสมอ

ตามที่คาดหวังจาก data stores ที่น่าเชื่อถือที่เสนอระดับความสม่ำเสมอนี้ การรับประกันเหล่านี้นำมาพร้อมกับการแลกเปลี่ยน (trade-offs) ด้านประสิทธิภาพและความพร้อมใช้งาน ใน RedisRaft:

  • การดำเนินการของไคลเอ็นต์ขึ้นอยู่กับการแลกเปลี่ยนข้อความระหว่างโนดของคลัสเตอร์ ดังนั้นจึงผูกมัดกับ network latency
  • การเขียนต้อง flush ไปยังดิสก์ก่อนเสร็จสิ้น ดังนั้นจึงผูกมัดกับ disk I/O latency
  • คลัสเตอร์พร้อมใช้งานได้เฉพาะเมื่อ majority ของโนดอยู่ในสถานะ up, healthy และสามารถสื่อสารกันได้

วิธีการทำงานของ RedisRaft

เมื่อโมดูล RedisRaft ถูกโหลดเข้า Redis มันจะ接管การสื่อสารระหว่างโนดของคลัสเตอร์ การจำลอง Raft log หรือ snapshots, persistence และอื่นๆ Redis core ยังคงไม่รู้เรื่องนี้ และ就它所關心的 它正作為一個獨立的伺服器運行,沒有集群、持久化或複製。

การตั้งค่าคลัสเตอร์ RedisRaft 3 โนดง่ายเท่ากับการเริ่มต้นเซิร์ฟเวอร์ Redis 3 ตัว ตามที่แสดงที่นี่:

redis-server --loadmodule /path/to/redisraft.so

นี่คือวิธีการเชื่อมต่อกับเซิร์ฟเวอร์แรกและสร้างคลัสเตอร์ Raft:

10.0.0.1:6379> RAFT.CLUSTER INIT
OK 989645460313dd2ddb051f033c791222

จากนั้นคุณเชื่อมต่อกับอีกสองเซิร์ฟเวอร์และเข้าร่วมพวกเขาเข้ากับคลัสเตอร์:

10.0.0.2:6379> RAFT.CLUSTER JOIN 10.0.0.1:6379
OK
10.0.0.3:6379> RAFT.CLUSTER JOIN 10.0.0.1:6379
OK

การเข้าถึงคลัสเตอร์

เมื่อ RedisRaft ตั้งค่าเสร็จ เราสามารถเขียนข้อมูลไปยังคลัสเตอร์ของเราได้:

10.0.0.1:6379> INCR counter:1
(integer) 1

การได้รับการตอบกลับแสดงว่าการเขียนของเราถูกจำลองไปยัง อย่างน้อย majority ของโนดคลัสเตอร์ (2 โนดในกรณีของเรา) และ committed ไปยัง persistent storage ของพวกเขา

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

การลองทำการดำเนินการเดียวกันบน follower (non-leader) โนด สร้างการตอบสนองนี้:

10.0.0.3:6379> INCR counter:1
(error) MOVED 10.0.0.1:6379

ดังนั้นในฐานะไคลเอ็นต์ เราสามารถจับข้อผิดพลาดนี้ สร้างการเชื่อมต่อใหม่กับโนด leader ตามที่ระบุ และลองคำสั่งของเราใหม่

แต่ถ้าเราไม่อยากแก้ไขแอปพลิเคชันที่มีอยู่? โชคดีที่ RedisRaft ยังสามารถกำหนดค่าให้จัดการเรื่องนี้ให้เราอัตโนมัติได้ ด้วยการเปิดใช้งาน follower proxy mode เราสามารถให้โนดของคลัสเตอร์ส่งต่อคำขอของเราไปยัง leader อัตโนมัติและให้การตอบกลับเมื่อพร้อม:

10.0.0.3:6379> RAFT.CONFIG SET follower-proxy yes
OK
10.0.0.3:6379> INCR counter:1
(integer) 2

นี่ง่ายกว่ามาก ทว่าส่งผลต่อ latency และ network load เนื่องจากการเข้าถึง non-leader โนดสร้าง network hop เพิ่ม

การเปลี่ยนแปลงคลัสเตอร์

เมื่อเราตั้งค่าคลัสเตอร์ เราได้ทำการดำเนินการ 3 อย่างที่แตกต่างกัน:

  1. สร้างคลัสเตอร์บนโนดเดียว
  2. เพิ่มโนดที่สอง
  3. เพิ่มโนดที่สาม

การกำหนดค่าคลัสเตอร์ RedisRaft ไม่ได้เป็นแบบคงที่ และสามารถเพิ่มหรือลบโนดเพิ่มเติมได้หลังจากที่คลัสเตอร์ถูกสร้างและขณะที่มัน active

ตัวอย่างเช่น เราอาจต้องการแทนที่โนดที่สามของเรา ก่อนอื่น เราเข้าร่วมโนดใหม่ที่จะแทนที่มัน โปรดทราบว่าเรา "add-then-remove" แทนที่จะเป็น "remove-then-add" เพื่อหลีกเลี่ยงการทิ้งคลัสเตอร์และข้อมูลที่มีค่าของเราในสถานะ degraded redundancy ระหว่างการเปลี่ยนผ่าน:

10.0.0.4:6379> RAFT.CLUSTER JOIN 10.0.0.1:6379
OK

ต่อไป เราค้นหา ID ที่ถูกกำหนดแบบสุ่มให้กับโนดที่สามของเรา:

redis-cli -h 10.0.0.1 --raw RAFT.INFO | grep 10.0.0.3
node2:id=1739451728,state=connected,voting=yes,addr=10.0.0.3,port=6379,
last_conn_secs=3537,conn_errors=0,conn_oks=1

และจากนั้นเราลบมัน:

10.0.0.1:6379> RAFT.NODE REMOVE 1739451728
OK

สถานะการเผยแพร่ RedisRaft

เป็นส่วนหนึ่งของงานพัฒนา RedisRaft เราได้ร่วมมือกับ Kyle Kingsbury (a.k.a Aphyr) เพื่อวิเคราะห์และทดสอบ RedisRaft โดยใช้ Jepsen เฟรมเวิร์กที่รู้จักกันดีสำหรับการทดสอบความปลอดภัยและความถูกต้องของระบบกระจาย การร่วมมือนี้จนถึงตอนนี้ได้ส่งผลเป็นการวิเคราะห์ที่เผยแพร่แล้ว

แม้ยังคงอยู่ระหว่างการพัฒนา ฟังก์ชันพื้นฐานส่วนใหญ่ของ RedisRaft อยู่ในที่แล้ว เรากำลังทำงานเพื่อเวอร์ชัน preview แรก ซึ่งคาดว่าจะพร้อมในอีกไม่กี่เดือน เมื่อพร้อมใช้งานทั่วไป RedisRaft จะถูกเผยแพร่ภายใต้ dual license คือ GNU AGPLv3 หรือ Redis Source Available License (RSAL)