คลัสเตอร์ Elasticsearch 200 TB+

คลัสเตอร์ Elasticsearch 200 TB+

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

พวกเราที่ Odnoklassniki ตัดสินใจใช้ elasticsearch เพื่อแก้ไขปัญหาการจัดการบันทึก และตอนนี้เราได้แบ่งปันประสบการณ์ของเรากับ Habr ทั้งเกี่ยวกับสถาปัตยกรรมและข้อผิดพลาด

ฉันชื่อ Pyotr Zaitsev ทำงานเป็นผู้ดูแลระบบที่ Odnoklassniki ก่อนหน้านั้น ฉันยังเป็นผู้ดูแลระบบ โดยทำงานร่วมกับ Manticore Search, Sphinx search, Elasticsearch บางที ถ้ามี ...การค้นหาอื่นปรากฏขึ้น ฉันก็อาจจะดำเนินการด้วย ฉันยังมีส่วนร่วมในโครงการโอเพ่นซอร์สหลายโครงการตามความสมัครใจ

เมื่อฉันมาที่ Odnoklassniki ฉันพูดอย่างไม่ใส่ใจในการสัมภาษณ์ว่าฉันสามารถทำงานร่วมกับ Elasticsearch ได้ หลังจากที่ฉันเข้าใจและทำงานง่ายๆ บางอย่างเสร็จแล้ว ฉันก็ได้รับมอบหมายงานใหญ่ให้ปฏิรูประบบการจัดการบันทึกที่มีอยู่ในเวลานั้น

ความต้องการ

ความต้องการของระบบถูกกำหนดไว้ดังนี้:

  • Graylog จะถูกนำมาใช้เป็นส่วนหน้า เนื่องจากบริษัทมีประสบการณ์ในการใช้ผลิตภัณฑ์นี้อยู่แล้ว โปรแกรมเมอร์และผู้ทดสอบจึงรู้ว่าผลิตภัณฑ์นี้คุ้นเคยและสะดวกสำหรับพวกเขา
  • ปริมาณข้อมูล: โดยเฉลี่ย 50-80 ข้อความต่อวินาที แต่หากมีสิ่งใดขัดข้อง ปริมาณการรับส่งข้อมูลก็ไม่ได้ถูกจำกัดด้วยสิ่งใดๆ อาจเป็น 2-3 ล้านบรรทัดต่อวินาที
  • เมื่อหารือกับลูกค้าเกี่ยวกับข้อกำหนดด้านความเร็วในการประมวลผลคำค้นหาแล้ว เราพบว่ารูปแบบทั่วไปของการใช้ระบบดังกล่าวคือ: ผู้คนกำลังมองหาบันทึกแอปพลิเคชันของตนในช่วงสองวันที่ผ่านมา และไม่ต้องการรอนานกว่า อันดับสองสำหรับผลลัพธ์ของการสืบค้นที่กำหนด
  • ผู้ดูแลระบบยืนยันว่าระบบสามารถปรับขนาดได้ง่ายหากจำเป็น โดยไม่จำเป็นต้องเจาะลึกถึงวิธีการทำงาน
  • ดังนั้นงานบำรุงรักษาเพียงอย่างเดียวที่ระบบเหล่านี้ต้องการเป็นระยะคือการเปลี่ยนฮาร์ดแวร์บางตัว
  • นอกจากนี้ Odnoklassniki ยังมีประเพณีทางเทคนิคที่ยอดเยี่ยม บริการใดๆ ที่เราเปิดตัวจะต้องรอดพ้นจากความล้มเหลวของศูนย์ข้อมูล (เกิดขึ้นอย่างกะทันหัน ไม่ได้วางแผนไว้ และเกิดขึ้นได้ตลอดเวลา)

ข้อกำหนดสุดท้ายในการดำเนินโครงการนี้ทำให้เราเสียค่าใช้จ่ายมากที่สุดซึ่งฉันจะพูดถึงรายละเอียดเพิ่มเติม

วันพุธ

เราทำงานในศูนย์ข้อมูลสี่แห่ง ในขณะที่โหนดข้อมูล Elasticsearch สามารถอยู่ในสามแห่งเท่านั้น (ด้วยเหตุผลหลายประการที่ไม่ใช่ด้านเทคนิค)

ศูนย์ข้อมูลทั้งสี่นี้มีแหล่งบันทึกที่แตกต่างกันประมาณ 18 แหล่ง - ฮาร์ดแวร์ คอนเทนเนอร์ เครื่องเสมือน

คุณลักษณะที่สำคัญ: คลัสเตอร์เริ่มต้นในคอนเทนเนอร์ พอดแมน ไม่ใช่บนเครื่องจริง แต่เปิดอยู่ ผลิตภัณฑ์คลาวด์ของตัวเองบนคลาวด์เดียว. คอนเทนเนอร์รับประกัน 2 คอร์ ซึ่งคล้ายกับ 2.0Ghz v4 โดยมีความเป็นไปได้ในการรีไซเคิลคอร์ที่เหลือหากไม่ได้ใช้งาน

กล่าวอีกนัยหนึ่ง:

คลัสเตอร์ Elasticsearch 200 TB+

โทโพโลยี

ในตอนแรกฉันเห็นรูปแบบทั่วไปของโซลูชันดังนี้:

  • VIP 3-4 คนอยู่เบื้องหลัง A-record ของโดเมน Graylog นี่คือที่อยู่สำหรับส่งบันทึก
  • VIP แต่ละคนคือบาลานเซอร์ LVS
  • หลังจากนั้น บันทึกจะถูกส่งไปยังแบตเตอรี่ Graylog ข้อมูลบางส่วนอยู่ในรูปแบบ GELF และบางส่วนอยู่ในรูปแบบ syslog
  • จากนั้นทั้งหมดนี้จะถูกเขียนเป็นชุดใหญ่ไปยังแบตเตอรี่ของผู้ประสานงาน Elasticsearch
  • และในทางกลับกัน พวกเขาก็ส่งคำขอเขียนและอ่านไปยังโหนดข้อมูลที่เกี่ยวข้อง

คลัสเตอร์ Elasticsearch 200 TB+

คำศัพท์

บางทีอาจไม่ใช่ทุกคนที่เข้าใจคำศัพท์โดยละเอียด ดังนั้นฉันอยากจะพูดถึงมันสักหน่อย

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

เจ้านาย
โดยจะส่ง Ping ไปยังโหนดทั้งหมดที่มีอยู่ในคลัสเตอร์ รักษาแผนที่คลัสเตอร์ที่ทันสมัย ​​และกระจายระหว่างโหนด ประมวลผลตรรกะเหตุการณ์ และดำเนินการดูแลทำความสะอาดทั่วทั้งคลัสเตอร์ประเภทต่างๆ

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

โหนดข้อมูล
จัดเก็บข้อมูล ดำเนินการค้นหาที่มาจากภายนอก และดำเนินการกับชาร์ดที่อยู่ในนั้น

เกรย์ล็อก
นี่เป็นสิ่งที่เหมือนกับการผสมผสานระหว่าง Kibana กับ Logstash ในสแต็ก ELK Graylog ผสมผสานทั้ง UI และไปป์ไลน์การประมวลผลบันทึก ภายใต้ประทุน Graylog เรียกใช้ Kafka และ Zookeeper ซึ่งให้การเชื่อมต่อกับ Graylog เป็นคลัสเตอร์ Graylog สามารถแคชบันทึก (Kafka) ในกรณีที่ Elasticsearch ไม่พร้อมใช้งานและทำซ้ำคำขออ่านและเขียนที่ไม่สำเร็จ จัดกลุ่มและทำเครื่องหมายบันทึกตามกฎที่ระบุ เช่นเดียวกับ Logstash Graylog มีฟังก์ชันในการแก้ไขแถวก่อนที่จะเขียนลงใน Elasticsearch

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

สายตาจะมีลักษณะดังนี้:

คลัสเตอร์ Elasticsearch 200 TB+

นี่คือภาพหน้าจอจากอินสแตนซ์เฉพาะ ที่นี่เราสร้างฮิสโตแกรมตามคำค้นหาและแสดงแถวที่เกี่ยวข้อง

ดัชนี

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

ในแผนภาพด้านบน นี่คือระดับต่ำสุด: โหนดข้อมูล Elasticsearch

ดัชนีคือเอนทิตีเสมือนขนาดใหญ่ที่ประกอบด้วยชาร์ด Elasticsearch ในตัวมันเอง แต่ละชาร์ดนั้นไม่มีอะไรมากไปกว่าดัชนีลูซีน และดัชนี Lucene แต่ละดัชนีจะประกอบด้วยหนึ่งส่วนขึ้นไป

คลัสเตอร์ Elasticsearch 200 TB+

เมื่อออกแบบ เราพบว่าเพื่อให้เป็นไปตามข้อกำหนดด้านความเร็วในการอ่านข้อมูลจำนวนมาก เราจำเป็นต้อง "กระจาย" ข้อมูลนี้เท่าๆ กันทั่วทั้งโหนดข้อมูล

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

ขั้นแรกเรากำหนดเวลาจัดเก็บเป็น 30 วัน

การกระจายตัวของเศษสามารถแสดงเป็นกราฟิกได้ดังนี้:

คลัสเตอร์ Elasticsearch 200 TB+

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

เมื่อเราเพิ่มชิ้นส่วนอื่น มันจะไปที่ศูนย์ข้อมูลแห่งที่สาม และท้ายที่สุด เราก็ได้โครงสร้างนี้ ซึ่งทำให้สามารถสูญเสีย DC โดยไม่สูญเสียความสอดคล้องของข้อมูล:

คลัสเตอร์ Elasticsearch 200 TB+

การหมุนของดัชนีเช่น การสร้างดัชนีใหม่และการลบดัชนีที่เก่าที่สุดเรากำหนดให้เท่ากับ 48 ชั่วโมง (ตามรูปแบบการใช้ดัชนี: 48 ชั่วโมงที่ผ่านมาถูกค้นหาบ่อยที่สุด)

ช่วงเวลาการหมุนเวียนดัชนีนี้เกิดจากสาเหตุดังต่อไปนี้:

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

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

เพื่อให้มีเวลาแฝงในการค้นหาที่จำเป็น เราจึงตัดสินใจใช้ SSD เพื่อประมวลผลคำขออย่างรวดเร็ว เครื่องที่โฮสต์คอนเทนเนอร์เหล่านี้ต้องมีอย่างน้อย 56 คอร์ เลือกตัวเลข 56 ให้เป็นค่าที่เพียงพอตามเงื่อนไขซึ่งกำหนดจำนวนเธรดที่ Elasticsearch จะสร้างระหว่างการดำเนินการ ใน Elasitcsearch พารามิเตอร์เธรดพูลจำนวนมากขึ้นอยู่กับจำนวนคอร์ที่มีอยู่โดยตรง ซึ่งจะส่งผลโดยตรงต่อจำนวนโหนดที่ต้องการในคลัสเตอร์ตามหลักการ “คอร์น้อยลง - โหนดมากขึ้น”

เป็นผลให้เราพบว่าโดยเฉลี่ยแล้วชาร์ดจะมีน้ำหนักประมาณ 20 กิกะไบต์ และมีชาร์ด 1 ต่อดัชนี ดังนั้น ถ้าเราหมุนเวียนพวกมันทุกๆ 360 ชั่วโมง เราก็จะมี 48 อัน แต่ละดัชนีมีข้อมูลเป็นเวลา 15 วัน

การเขียนและอ่านข้อมูลวงจร

เรามาดูกันว่าข้อมูลถูกบันทึกในระบบนี้อย่างไร

สมมติว่าคำขอบางอย่างมาถึงจาก Graylog ไปยังผู้ประสานงาน ตัวอย่างเช่น เราต้องการสร้างดัชนี 2-3 พันแถว

ผู้ประสานงานที่ได้รับคำขอจาก Graylog ได้ตั้งคำถามกับอาจารย์ว่า "ในคำขอจัดทำดัชนี เราได้ระบุดัชนีไว้โดยเฉพาะ แต่ไม่ได้ระบุส่วนที่จะเขียนไว้"

ต้นแบบตอบกลับ: “เขียนข้อมูลนี้ไปยังชิ้นส่วนหมายเลข 71” หลังจากนั้นข้อมูลจะถูกส่งโดยตรงไปยังโหนดข้อมูลที่เกี่ยวข้อง ซึ่งเป็นที่ตั้งของชิ้นส่วนหลักหมายเลข 71

หลังจากนั้นบันทึกธุรกรรมจะถูกจำลองไปยังส่วนจำลองซึ่งตั้งอยู่ในศูนย์ข้อมูลอื่น

คลัสเตอร์ Elasticsearch 200 TB+

คำขอค้นหามาจาก Graylog ถึงผู้ประสานงาน ผู้ประสานงานจะเปลี่ยนเส้นทางตามดัชนี ในขณะที่ Elasticsearch กระจายคำขอระหว่างชิ้นส่วนหลักและชิ้นส่วนจำลองโดยใช้หลักการปัดเศษ

คลัสเตอร์ Elasticsearch 200 TB+

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

โดยเฉลี่ยทั้งระบบนี้จะประมวลผลคำค้นหาในช่วง 48 ชั่วโมงที่ผ่านมาในเวลา 300-400 มิลลิวินาที ยกเว้นคำค้นหาเหล่านั้นที่มีไวด์การ์ดนำหน้า

ดอกไม้พร้อม Elasticsearch: การตั้งค่า Java

คลัสเตอร์ Elasticsearch 200 TB+

เพื่อให้ทุกอย่างเป็นไปตามที่เราต้องการในตอนแรก เราใช้เวลานานมากในการดีบักสิ่งต่าง ๆ ในคลัสเตอร์

ส่วนแรกของปัญหาที่ค้นพบเกี่ยวข้องกับวิธีที่ Java ได้รับการกำหนดค่าล่วงหน้าตามค่าเริ่มต้นใน Elasticsearch

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

ปรากฎว่าการรวมดัชนี Lucene เกิดขึ้นนอกสะโพก และคอนเทนเนอร์ค่อนข้างจำกัดในแง่ของทรัพยากรที่ใช้ มีเพียงฮีปเท่านั้นที่สามารถใส่ลงในทรัพยากรเหล่านี้ได้ (ค่า heap.size เท่ากับ RAM โดยประมาณ) และการดำเนินการนอกฮีปบางอย่างล้มเหลวด้วยข้อผิดพลาดในการจัดสรรหน่วยความจำ หากไม่พอดีกับ ~500MB ที่ยังคงอยู่ก่อนขีดจำกัดด้วยเหตุผลบางประการ

การแก้ไขค่อนข้างเล็กน้อย: จำนวน RAM ที่พร้อมใช้งานสำหรับคอนเทนเนอร์เพิ่มขึ้น หลังจากนั้นเราลืมไปว่าเราประสบปัญหาดังกล่าวด้วยซ้ำ

ปัญหาที่สอง
4-5 วันหลังจากการเปิดตัวคลัสเตอร์ เราสังเกตเห็นว่าโหนดข้อมูลเริ่มหลุดออกจากคลัสเตอร์เป็นระยะและเข้ามาหลังจากผ่านไป 10-20 วินาที

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

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

วิธีแก้ปัญหามีดังนี้: เราจำกัดความสามารถของ Java ในการใช้หน่วยความจำจำนวนมากนอกฮีปสำหรับการดำเนินการเหล่านี้ เราจำกัดไว้ที่ 16 กิกะไบต์ (-XX:MaxDirectMemorySize=16g) ทำให้มั่นใจได้ว่า GC ที่ชัดเจนจะถูกเรียกบ่อยกว่ามากและประมวลผลได้เร็วกว่ามาก จึงไม่ทำให้คลัสเตอร์ไม่เสถียรอีกต่อไป

ปัญหาที่สาม
หากคุณคิดว่าปัญหา “โหนดออกจากคลัสเตอร์ในช่วงเวลาที่ไม่คาดคิดที่สุด” จบลงแล้ว แสดงว่าคุณคิดผิด

เมื่อเรากำหนดค่างานด้วยดัชนี เราเลือก mmapfs ลดเวลาในการค้นหา บนเศษสดที่มีการแบ่งส่วนที่ดี นี่เป็นความผิดพลาดค่อนข้างมาก เนื่องจากเมื่อใช้ mmapfs ไฟล์จะถูกแมปเข้ากับ RAM จากนั้นเราจะทำงานกับไฟล์ที่แมป ด้วยเหตุนี้ปรากฎว่าเมื่อ GC พยายามหยุดเธรดในแอปพลิเคชันเราจะไปที่จุดปลอดภัยเป็นเวลานานมากและระหว่างทางไปนั้นแอปพลิเคชันจะหยุดตอบสนองต่อคำขอของอาจารย์ว่ายังมีชีวิตอยู่หรือไม่ . ดังนั้นต้นแบบจึงเชื่อว่าโหนดไม่มีอยู่ในคลัสเตอร์อีกต่อไป หลังจากนั้นหลังจากผ่านไป 5-10 วินาที ตัวรวบรวมขยะจะทำงาน โหนดกลับมามีชีวิตอีกครั้ง เข้าสู่คลัสเตอร์อีกครั้ง และเริ่มเริ่มต้นการแบ่งส่วน ทุกอย่างให้ความรู้สึกเหมือนเป็น "ผลงานที่เราสมควรได้รับ" มาก และไม่เหมาะกับอะไรที่จริงจังเลย

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

ปัญหาที่สี่
แล้วก็มีปัญหาที่น่าสนใจอีกปัญหาหนึ่งที่เรารักษามาเป็นเวลายาวนานเป็นประวัติการณ์ เราจับได้ 2-3 เดือน เพราะรูปแบบมันเข้าใจยากจริงๆ

บางครั้งผู้ประสานงานของเราไปที่ Full GC ซึ่งมักจะเป็นช่วงหลังอาหารกลางวัน และไม่เคยกลับมาจากที่นั่นเลย ในเวลาเดียวกันเมื่อบันทึกความล่าช้า GC ดูเหมือนว่าทุกอย่างเป็นไปด้วยดี ดี ดี และทันใดนั้นทุกอย่างก็แย่มาก

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

เป็นผลให้ปรากฏว่าในขณะที่ผู้ใช้ส่งคำขอจำนวนมาก และไปถึงผู้ประสานงาน Elasticsearch ที่เฉพาะเจาะจง บางโหนดก็ตอบสนองนานกว่าโหนดอื่นๆ

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

การแก้ไขเดียวที่เราพบว่าเปลี่ยนพฤติกรรมของคลัสเตอร์ในสถานการณ์นี้คือการย้ายไปยัง JDK13 และการใช้ตัวรวบรวมขยะ Shenandoah วิธีนี้ช่วยแก้ปัญหาได้ ผู้ประสานงานของเราหยุดล้ม

นี่คือจุดที่ปัญหาเกี่ยวกับ Java สิ้นสุดลงและปัญหาแบนด์วิดท์เริ่มต้นขึ้น

"เบอร์รี่" พร้อม Elasticsearch: ปริมาณงาน

คลัสเตอร์ Elasticsearch 200 TB+

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

อาการแรกที่พบ: ในระหว่าง "การระเบิด" ในการใช้งานจริง เมื่อมีการสร้างบันทึกจำนวนมากอย่างกะทันหัน ข้อผิดพลาดในการจัดทำดัชนี es_rejected_execution จะเริ่มกะพริบบ่อยครั้งใน Graylog

นี่เป็นเพราะว่า thread_pool.write.queue บนโหนดข้อมูลเดียว จนถึงช่วงเวลาที่ Elasticsearch สามารถประมวลผลคำขอจัดทำดัชนีและอัปโหลดข้อมูลไปยังส่วนแบ่งบนดิสก์ จะสามารถแคชคำขอได้เพียง 200 รายการตามค่าเริ่มต้นเท่านั้น และใน เอกสารประกอบ Elasticsearch มีการพูดถึงพารามิเตอร์นี้น้อยมาก ระบุเฉพาะจำนวนเธรดสูงสุดและขนาดเริ่มต้นเท่านั้น

แน่นอนว่า เราได้บิดค่านี้และพบสิ่งต่อไปนี้: โดยเฉพาะในการตั้งค่าของเรา มีการแคชคำขอมากถึง 300 รายการได้ค่อนข้างดี และค่าที่สูงกว่านั้นเต็มไปด้วยความจริงที่ว่าเราจะบินไปที่ Full GC อีกครั้ง

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

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

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

พวกเขาเริ่มคิดออก ในด้านหนึ่ง เห็นได้ชัดว่าทั้งคำค้นหาและคำค้นหาที่จัดทำดัชนีได้รับการประมวลผลบนเครื่องจริงเดียวกัน และไม่ทางใดก็ทางหนึ่งที่จะมีการเบิกจ่ายบางอย่าง

แต่สิ่งนี้อาจถูกหลีกเลี่ยงได้บางส่วนเนื่องจากข้อเท็จจริงที่ว่าใน Elasticsearch เวอร์ชันที่หก มีอัลกอริธึมปรากฏขึ้นที่ช่วยให้คุณสามารถกระจายการสืบค้นระหว่างโหนดข้อมูลที่เกี่ยวข้องซึ่งไม่เป็นไปตามหลักการสุ่มแบบวนรอบ (คอนเทนเนอร์ที่ทำดัชนีและเก็บหลัก -shard อาจยุ่งมาก ไม่มีทางที่จะตอบสนองได้อย่างรวดเร็ว) แต่ในการส่งต่อคำขอนี้ไปยังคอนเทนเนอร์ที่โหลดน้อยกว่าด้วย Replica-shard ซึ่งจะตอบสนองเร็วกว่ามาก กล่าวอีกนัยหนึ่ง เรามาถึง use_adaptive_replica_selection: true

รูปภาพการอ่านเริ่มมีลักษณะดังนี้:

คลัสเตอร์ Elasticsearch 200 TB+

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

สุดท้ายนี้ ปัญหาหลักคือการถอดศูนย์ข้อมูลออกโดยไม่ยุ่งยาก

สิ่งที่เราต้องการจากคลัสเตอร์ทันทีหลังจากสูญเสียการเชื่อมต่อกับ DC หนึ่งตัว:

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

ปรากฎว่าเราต้องการสิ่งนี้:

คลัสเตอร์ Elasticsearch 200 TB+

และเราได้รับสิ่งต่อไปนี้:

คลัสเตอร์ Elasticsearch 200 TB+

มันเกิดขึ้นได้อย่างไร?

เมื่อศูนย์ข้อมูลล่ม เจ้านายของเรากลายเป็นคอขวด

ทำไม?

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

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

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

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

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

มันดูเหมือนสิ่งนี้:

คลัสเตอร์ Elasticsearch 200 TB+

หลังจากเวอร์ชัน 6.4.0 ซึ่งข้อบกพร่องร้ายแรงนี้ได้รับการแก้ไขแล้ว โหนดข้อมูลก็หยุดฆ่าต้นแบบ แต่นั่นไม่ได้ทำให้เขา "ฉลาดขึ้น" กล่าวคือ เมื่อเราส่งออกโหนดข้อมูล 2, 3 หรือ 10 (หมายเลขใดๆ นอกเหนือจากหนึ่ง) ต้นแบบจะได้รับข้อความแรกที่แจ้งว่าโหนด A ออกไปแล้ว และพยายามบอกโหนด B โหนด C เกี่ยวกับเรื่องนี้ โหนด D

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

โดยหลักการแล้ว สิ่งนี้สอดคล้องกับข้อกำหนดที่นำเสนอในตอนแรกกับผลิตภัณฑ์ขั้นสุดท้ายซึ่งเป็นส่วนหนึ่งของโครงการ แต่จากมุมมองของ "วิทยาศาสตร์บริสุทธิ์" นี่เป็นข้อบกพร่อง ซึ่งนักพัฒนาได้แก้ไขเรียบร้อยแล้วในเวอร์ชัน 7.2

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

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

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

เป็นผลให้เราตัดสินใจดังต่อไปนี้:

  • เรามีโหนดข้อมูล 360 พร้อมดิสก์ขนาด 700 กิกะไบต์
  • ผู้ประสานงาน 60 คนสำหรับการกำหนดเส้นทางการรับส่งข้อมูลผ่านโหนดข้อมูลเดียวกันเหล่านี้
  • ผู้เชี่ยวชาญ 40 คนที่เราทิ้งไว้เป็นมรดกตั้งแต่เวอร์ชันก่อน 6.4.0 - เพื่อความอยู่รอดจากการถูกถอนออกจากศูนย์ข้อมูล เราได้เตรียมใจที่จะสูญเสียเครื่องหลายเครื่องเพื่อรับประกันว่าจะมีองค์ประชุมของผู้เชี่ยวชาญแม้ใน สถานการณ์กรณีที่เลวร้ายที่สุด
  • ความพยายามใด ๆ ที่จะรวมบทบาทในคอนเทนเนอร์เดียวนั้นพบกับความจริงที่ว่าไม่ช้าก็เร็วโหนดจะพังภายใต้ภาระงาน
  • คลัสเตอร์ทั้งหมดใช้ heap.size 31 กิกะไบต์: ความพยายามทั้งหมดในการลดขนาดส่งผลให้เกิดการฆ่าบางโหนดจากคำค้นหาจำนวนมากที่มีไวด์การ์ดนำหน้า หรือทำให้เซอร์กิตเบรกเกอร์ใน Elasticsearch เอง
  • นอกจากนี้ เพื่อให้มั่นใจในประสิทธิภาพการค้นหา เราพยายามรักษาจำนวนอ็อบเจ็กต์ในคลัสเตอร์ให้น้อยที่สุดเท่าที่จะเป็นไปได้ เพื่อประมวลผลเหตุการณ์ให้น้อยที่สุดเท่าที่จะทำได้ในช่วงคอขวดที่เราได้รับในต้นแบบ

สุดท้ายเกี่ยวกับการตรวจสอบ

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

  • โหนดข้อมูลแต่ละโหนดจะรายงานไปยังคลาวด์ของเราว่ามีข้อมูลดังกล่าวอยู่ และมีชิ้นส่วนดังกล่าวอยู่ด้วย เมื่อเราดับบางสิ่งบางอย่างที่ไหนสักแห่ง คลัสเตอร์จะรายงานหลังจากผ่านไป 2-3 วินาทีว่าตรงกลาง A เราดับโหนด 2, 3 และ 4 ซึ่งหมายความว่าในศูนย์ข้อมูลอื่นๆ เราไม่สามารถดับโหนดเหล่านั้นที่มีชิ้นส่วนเพียงชิ้นเดียวได้ไม่ว่าในสถานการณ์ใดก็ตาม ซ้าย.
  • เมื่อทราบถึงลักษณะของพฤติกรรมของอาจารย์แล้ว เราจะพิจารณาจำนวนงานที่ค้างอยู่อย่างรอบคอบ เนื่องจากแม้แต่งานเดียวที่ติดอยู่ หากไม่หมดเวลาตามทฤษฎี ในสถานการณ์ฉุกเฉินบางอย่าง อาจกลายเป็นสาเหตุที่ทำให้การเลื่อนระดับส่วนแบ่งข้อมูลจำลองในส่วนหลักไม่ทำงาน ซึ่งเป็นสาเหตุที่ทำให้การจัดทำดัชนีหยุดทำงาน
  • นอกจากนี้เรายังพิจารณาความล่าช้าของตัวรวบรวมขยะอย่างใกล้ชิด เนื่องจากเราประสบปัญหาอย่างมากกับสิ่งนี้ในระหว่างการปรับให้เหมาะสม
  • ปฏิเสธทีละเธรดเพื่อทำความเข้าใจล่วงหน้าว่าปัญหาคอขวดอยู่ที่ใด
  • หน่วยวัดมาตรฐาน เช่น ฮีป RAM และ I/O

เมื่อสร้างการตรวจสอบ คุณต้องคำนึงถึงคุณสมบัติของ Thread Pool ใน Elasticsearch เอกสารประกอบ Elasticsearch อธิบายตัวเลือกการกำหนดค่าและค่าเริ่มต้นสำหรับการค้นหาและการจัดทำดัชนี แต่เงียบสนิทเกี่ยวกับ thread_pool.management โดยเฉพาะอย่างยิ่งกระบวนการเธรดเหล่านี้ คำสั่งเช่น _cat/shards และคำสั่งอื่น ๆ ที่คล้ายกัน ซึ่งสะดวกในการใช้เมื่อเขียนการตรวจสอบ ยิ่งคลัสเตอร์มีขนาดใหญ่เท่าใด คำร้องขอดังกล่าวจะถูกดำเนินการต่อหน่วยเวลามากขึ้นเท่านั้น และ thread_pool.management ที่กล่าวมาข้างต้นไม่เพียงแต่ไม่ได้นำเสนอในเอกสารอย่างเป็นทางการเท่านั้น แต่ยังถูกจำกัดโดยค่าเริ่มต้นไว้ที่ 5 เธรด ซึ่งจะถูกกำจัดอย่างรวดเร็วหลังจากนั้น ซึ่งการตรวจสอบหยุดทำงานอย่างถูกต้อง

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

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

คลัสเตอร์ Elasticsearch 200 TB+

ที่มา: will.com

เพิ่มความคิดเห็น