คุณจะทำให้คลัสเตอร์ทำงานเพียงครั้งเดียวได้อย่างไร


13

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

ใช้กรณี:คุณมีงานที่มีราคาแพงในการทำงานที่ควรรันเพียงครั้งเดียวต่อหนึ่งชั่วโมง X งานนี้สามารถทำซ้ำได้หลายระเบียนและอัพเดทสถานะของพวกเขา

  • สถานการณ์กรณีที่เลวร้ายที่สุดคือการให้งานรันสองครั้งทำให้ข้อมูลของคุณไม่ถูกต้อง
  • สถานการณ์กรณีที่ดีที่สุดคืองานใช้ทรัพยากรในเซิร์ฟเวอร์ของคุณทั้งหมด

สรุปความต้องการ:

  1. งานจะต้องยังคงทำงานแม้ว่าหนึ่งในโหนดจะไม่ทำงาน
  2. งานต้องถูกเรียกใช้หนึ่งครั้งต่อหนึ่งตารางเวลาเท่านั้น
  3. หากมีการกำหนดเวลางานหลายงานในเวลาเดียวกันหรือในเวลาที่ทับซ้อนกันจำนวนงานที่รันจะถูกกระจายระหว่างเซิร์ฟเวอร์อย่างเท่าเทียมกัน
  4. เครื่องจะต้องมีรหัสฐานเดียวกันและจะทำข้อมูลให้ตรงกันผ่าน NTP
  5. การกำหนดค่าอาจแตกต่างกันระหว่างโหนดและโหนดโดยตัวแปรสภาพแวดล้อม
  6. งานต้องเริ่มตรงเวลาหรือภายในช่วงเวลาที่กำหนดของเวลาที่กำหนด (เช่นพูด 5 นาที)

การแก้ปัญหาที่เป็นไปได้

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

สิ่งนี้จะต้องทำงานใน Java ในภาชนะ servlet อย่างไรก็ตามมันไม่ได้เข้ารหัสงานที่ฉันกำลังมองหา

แน่นอนว่านี่เป็นปัญหาที่แก้ไขแล้วด้วยทางออกที่ดีที่สุดที่รู้จัก


คำถามที่เกี่ยวข้อง /programming/5949038/schedule-job-executes-twice-on-cluster

สิ่งนี้ไม่ซ้ำกันเนื่องจากโซลูชันไม่เพียงพอตามข้อกำหนด 5 ข้อที่ระบุด้านบน วิธีแก้ปัญหาที่ upvote มากที่สุดนั้นเกิดจากปัญหาการแข่งขันและวิธีที่สองนั้นเป็นการละเมิดข้อกำหนด 3

คำตอบ:


16

คุณมีฐานข้อมูลที่แชร์หรือไม่ ฉันเคยทำสิ่งนี้โดยใช้ฐานข้อมูลเป็นผู้ตัดสินในอดีต

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

SELECT TOP 1 *
FROM jobs
WHERE state = 'NotRun'
ORDER BY run_time ASC

วิธีการที่พวกเขาทั้งหมดจะมารับงานที่มีกำหนดที่จะทำงานต่อไป พวกเขานอนหลับทั้งหมดเพื่อให้พวกเขาตื่นขึ้นมาเมื่องานควรจะทำงานจริง จากนั้นพวกเขาทั้งหมดทำสิ่งนี้:

UPDATE jobs
SET state = 'Running'
WHERE job_id = :id
  AND state = 'NotRun'

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

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


1
คุณใช้ระดับ isloation ในระดับใด อ่านความมุ่งมั่นหรือต่อเนื่อง?
ไม่ฝักใฝ่ฝ่ายใด Riz

2

เซิร์ฟเวอร์แอปหลายตัวมีคุณสมบัติสำหรับ "บริการคลัสเตอร์เดี่ยวกว้าง"

ตัวอย่างเช่น Weblogic มีคุณลักษณะ Singleton Service ที่กำหนดค่าผ่านคอนโซลผู้ดูแลเว็บ

คุณต้องเขียนคลาสที่ใช้ weblogic.cluster.singleton.SingletonService และใช้เพื่อประกาศบริการในคอนโซลผู้ดูแลระบบ คลัสเตอร์ดูแลอินสแตนซ์ของคลาสและแจ้งให้คุณทราบเมื่อเซอร์วิสเริ่มทำงานหรือหยุดทำงาน อินเตอร์เฟส SingletonService มีวิธีเปิดใช้งาน () และวิธีปิดใช้งาน ()

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

http://docs.oracle.com/cd/E12839_01/apirefs.1111/e13952/taskhelp/clusters/ConfigureSingletonService.html

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.