รูปแบบสำหรับการรักษาความสอดคล้องในระบบเหตุการณ์ที่แจกจ่ายแบบกระจาย?


12

ฉันได้อ่านเกี่ยวกับการจัดหากิจกรรมเมื่อเร็ว ๆ นี้และชอบความคิดที่อยู่เบื้องหลัง แต่ติดอยู่กับปัญหาต่อไปนี้

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

ตอนนี้สมมติว่าเรามีกฎเกณฑ์ทางธุรกิจดังต่อไปนี้ผู้ใช้แต่ละคนต้องมีชื่อผู้ใช้ที่ไม่ซ้ำกัน

หากทั้งสองกระบวนการได้รับคำสั่งการลงทะเบียนผู้ใช้สำหรับชื่อผู้ใช้ X เดียวกันพวกเขาทั้งคู่ตรวจสอบว่า X ไม่ได้อยู่ในรายการชื่อผู้ใช้กฎจะตรวจสอบความถูกต้องของกระบวนการทั้งสองและพวกเขาทั้งสองเก็บเหตุการณ์ "ผู้ใช้ใหม่ .

ขณะนี้เราได้ป้อนสถานะโกลบอลที่ไม่สอดคล้องกันเนื่องจากละเมิดกฎธุรกิจ (มีผู้ใช้สองรายที่แตกต่างกันด้วยชื่อผู้ใช้เดียวกัน)

ในเซิร์ฟเวอร์ N แบบดั้งเดิม <-> 1 ระบบสไตล์ RDBMS ฐานข้อมูลจะใช้เป็นจุดศูนย์กลางของการซิงโครไนซ์ซึ่งช่วยป้องกันความไม่สอดคล้องดังกล่าว

คำถามของฉันคือโดยทั่วไปแล้วเหตุการณ์ที่มาจากระบบจะแก้ไขปัญหานี้ได้อย่างไร พวกเขาเพียงแค่ประมวลผลทุกคำสั่งตามลำดับ (เช่น จำกัด จำนวนของกระบวนการที่สามารถเขียนไปยังร้านค้าถึง 1)?


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

@Laiv ถูกต้อง เพื่อความง่ายฉันคิดว่าไม่มีฐานข้อมูลทุกสถานะเก็บไว้ในหน่วยความจำ การประมวลผลคำสั่งเฉพาะตามลำดับผ่านคิวจะเป็นตัวเลือก แต่รู้สึกว่ามันซับซ้อนในการตัดสินใจว่าคำสั่งใดมีผลต่อผู้อื่นและฉันอาจจะวางคำสั่งทั้งหมดในคิวเดียวกันซึ่งมีจำนวนคำสั่งประมวลผลกระบวนการเดียว : / ตัวอย่างเช่นถ้าฉันมีผู้ใช้เพิ่มความคิดเห็นในโพสต์บล็อก "ลบผู้ใช้", "ระงับผู้ใช้", "ลบโพสต์บล็อก", "ปิดการใช้งานความคิดเห็นโพสต์บล็อก" ฯลฯ ควรจะอยู่ในคิวเดียวกัน
Olivier Lalonde

1
ฉันเห็นด้วยกับคุณในการทำงานกับคิวหรือเซมาฟอร์ไม่ใช่เรื่องง่าย ไม่สามารถทำงานกับรูปแบบการทำงานพร้อมกันหรือเหตุการณ์แหล่งที่มา แต่โดยพื้นฐานแล้วโซลูชันทั้งหมดจะจบลงด้วยการรับส่งข้อมูลเหตุการณ์ของระบบ อย่างไรก็ตามมันเป็นกระบวนทัศน์ที่น่าสนใจ นอกจากนี้ยังมีแคชภายนอกที่เน้นไปที่ tuples เช่น Redis ที่สามารถช่วยจัดการทราฟฟิกระหว่างโหนดเช่นแคชสถานะสุดท้ายของเอนทิตีหรือหากมีการประมวลผลเอนทิตีในขณะนี้ แคชที่ใช้ร่วมกันเป็นเรื่องธรรมดาในการพัฒนาประเภทนี้ มันอาจดูซับซ้อน แต่อย่ายอมแพ้ ;-) มันค่อนข้างน่าสนใจ
2559

คำตอบ:


6

ในเซิร์ฟเวอร์ N แบบดั้งเดิม <-> 1 ระบบสไตล์ RDBMS ฐานข้อมูลจะใช้เป็นจุดศูนย์กลางของการซิงโครไนซ์ซึ่งช่วยป้องกันความไม่สอดคล้องดังกล่าว

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

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

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

Greg Young ในการตรวจสอบชุด

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

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

ในบางกรณีที่ที่เก็บเหตุการณ์ของคุณเก่งในการตรวจสอบความถูกต้องของการตั้งค่า (เช่น: ฐานข้อมูลเชิงสัมพันธ์) จากนั้นคุณใช้ข้อกำหนดโดยการเขียนลงในตาราง "ชื่อเฉพาะ" ในธุรกรรมเดียวกันที่ยังคงมีอยู่

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


1) ขอบคุณสำหรับคำแนะนำและการอ้างอิง เมื่อคุณพูดว่า "เปรียบเทียบและสลับ" คุณหมายถึงกระบวนการที่จะจัดเก็บเหตุการณ์หรือไม่เมื่อตรวจพบเหตุการณ์ใหม่ที่เกิดขึ้นตั้งแต่เริ่มประมวลผลคำสั่ง ฉันเดาว่านี่จะต้องมีร้านค้ากิจกรรมที่รองรับซีแมนติก "เปรียบเทียบและสลับ" ถูกต้องไหม (เช่น "เขียนเหตุการณ์นี้เท่านั้นและถ้าเหตุการณ์สุดท้ายมี ID X")
Olivier Lalonde

2) ฉันชอบความคิดในการยอมรับความไม่สอดคล้องกันชั่วคราวและซ่อมแซมมันในที่สุด แต่ฉันไม่แน่ใจว่าฉันจะเขียนโค้ดอย่างไรในวิธีที่เชื่อถือได้ ... อาจมีกระบวนการเฉพาะที่จะตรวจสอบเหตุการณ์ตามลำดับและสร้างเหตุการณ์ย้อนกลับเมื่อตรวจพบ อะไรบางอย่างผิดปกติ? ขอบคุณ!
Olivier Lalonde

(1) ฉันจะพูดว่า "ประวัติรุ่นใหม่" มากกว่า "เหตุการณ์ใหม่" แต่คุณมีความคิด แทนที่ประวัติเท่านั้นหากเป็นสิ่งที่เราคาดหวัง
VoiceOfUnreason

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

2

เสียงเหมือนคุณสามารถใช้กระบวนการทางธุรกิจ ( sagaในบริบทของDomain Driven Design) CRDTสำหรับการลงทะเบียนผู้ใช้ที่ผู้ใช้จะได้รับการปฏิบัติเช่น

ทรัพยากร

  1. https://doc.akka.io/docs/akka/current/distributed-data.html http://archive.is/t0QIx

  2. "CRDTs กับ Akka Distributed Data" https://www.slideshare.net/markusjura/crdts-with-akka-distributed-dataเพื่อเรียนรู้เกี่ยวกับ

    • CmRDTs - การดำเนินงานตาม CRDT
    • CvRDTs - CRTDs ตามรัฐ
  3. ตัวอย่างรหัสใน Scala https://github.com/akka/akka-samples/tree/master/akka-sample-distributed-data-scala บางที "ตะกร้าสินค้า" อาจเหมาะสมที่สุด

  4. ทัวร์ของ Akka Cluster - Akka กระจายข้อมูล https://manuel.bernhardt.io/2018/01/03/tour-akka-cluster-akka-distributed-data/
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.