กับดักงาน Cron ในช่วงเปลี่ยนเวลา: เหตุใดเซิร์ฟเวอร์ของคุณอาจทำงานผิดพลาด

ทีมชุมชน BigGo
กับดักงาน Cron ในช่วงเปลี่ยนเวลา: เหตุใดเซิร์ฟเวอร์ของคุณอาจทำงานผิดพลาด

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

ปัญหา Cron กับการเปลี่ยนเวลา

ปัญหาหลักอยู่ที่วิธีที่ cron จัดการกับการเปลี่ยนแปลงเวลาปีละสองครั้ง เมื่อนาฬิกาเดินหน้าไปหนึ่งชั่วโมง ช่วงเวลานั้นก็หายไปอย่างมีประสิทธิภาพ ซึ่งอาจทำให้งานที่กำหนดไว้ถูกข้ามไป ในทางกลับกัน เมื่อนาฬิกาถอยหลัง ชั่วโมงเดียวกันนั้นจะเกิดขึ้นสองครั้ง ซึ่งอาจนำไปสู่การที่งานทำงานหลายครั้ง ผู้ดูแลระบบท่านหนึ่งได้แบ่งปันตัวอย่างที่ชัดเจนของปัญหานี้: บน Linux ที่ใช้ vixie-cron เราเห็นงาน cron สองงานทำงานประมาณหนึ่งครั้งต่อวินาทีระหว่างเวลา 3:00 น. ถึง 3:01 น. เมื่อการเปลี่ยนเวลาไป-กลับมาเริ่มขึ้นครั้งล่าสุด ดังนั้นพวกมันจึงทำงานประมาณ 60 ครั้ง และขัดขวางการทำงานของกันและกัน การทำงานซ้ำเช่นนี้อาจทำให้เกิดการแย่งชิงทรัพยากร ความเสียหายของข้อมูล หรือความไม่เสถียรของระบบ ขึ้นอยู่กับว่างานที่กำหนดเวลาไว้กำลังทำอะไรอยู่

ปัญหาไม่ได้จำกัดอยู่ที่การใช้งานเฉพาะใด ๆ — มันเป็นเรื่องพื้นฐานเกี่ยวกับวิธีการที่การจัดกำหนดการตามเวลามีปฏิสัมพันธ์กับการเปลี่ยนแปลงเวลาแบบไม่เป็นเส้นตรง การใช้งาน cron ที่แตกต่างกันจัดการกับกรณีขอบเหล่านี้แตกต่างกันไป โดยบางตัวฉลาดกว่าตัวอื่นๆ ในการตรวจจับและจัดการกับการกระโดดของเวลา

พฤติกรรมทั่วไปของการทำงาน Cron ในช่วง DST:

  • Vixie-cron: อาจรันงานหลายครั้งในช่วงการเปลี่ยนแปลง "fall back"
  • BusyBox cron: การทำงานแบบเบาที่มีตรรกะ DST น้อยที่สุด
  • systemd timers: การจัดการเวลาที่ซับซ้อนมากขึ้นใน Linux distributions สมัยใหม่

ทางออกด้วย UTC และข้อจำกัด

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

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

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

กลยุทธ์การจัดกำหนดการทางเลือก

นอกเหนือจากคำแนะนำพื้นฐานเรื่อง UTC แล้ว ชุมชนยังได้พัฒนากลยุทธ์ที่ใช้งานได้จริงหลายประการสำหรับการจัดกำหนดการที่แข็งแกร่ง หลายคนแนะนำให้หลีกเลี่ยงเวลาที่เป็นเลขกลมๆ เช่น ตี 2 ตรง และให้ใช้เวลาที่ไม่ค่อยมีใครใช้ในช่วงนอกชั่วโมงเร่งด่วนแทน เช่น ตี 2 สิบสามนาที หรือ ตี 3 สี่สิบสองนาที สิ่งนี้ไม่เพียงแต่ช่วยหลีกเลี่ยงช่วงเวลาการเปลี่ยนเวลาไป-กลับมาเท่านั้น แต่ยังลดการแย่งชิงทรัพยากรเมื่อหลายระบบอาจกำลังกำหนดเวลางานบำรุงรักษาพร้อมกัน

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

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

แนวทางปฏิบัติที่แนะนำสำหรับการกำหนดตารางเวลา:

  • ใช้ UTC สำหรับเขตเวลาของเซิร์ฟเวอร์เมื่อเป็นไปได้
  • หลีกเลี่ยงการกำหนดตารางเวลาที่ 2:00 AM และ 3:00 AM ในเขตเวลาที่มี DST
  • พิจารณาการกำหนดตารางเวลาแบบนาทีคี่ (เช่น 2:13 AM แทนที่จะเป็น 2:00 AM)
  • ใช้งานการล็อคงานด้วยเครื่องมืออย่าง flock
  • สร้างความเป็น idempotence ให้กับงานที่กำหนดตารางเวลาไว้

ปัจจัยมนุษย์ในการจัดการเวลา

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

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

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

อ้างอิง: Avoid 2:00 and 3:00 am cron jobs!