MySQL Sharding เข้าใกล้?


89

แนวทางที่ดีที่สุดสำหรับตาราง Sharding MySQL คืออะไร แนวทางที่ฉันคิดได้คือ:

  1. การแบ่งระดับแอปพลิเคชัน?
  2. Sharding ที่ MySQL proxy layer?
  3. เซิร์ฟเวอร์การค้นหาส่วนกลางสำหรับการชาร์ด?

คุณรู้จักโครงการหรือเครื่องมือที่น่าสนใจในพื้นที่นี้หรือไม่?

คำตอบ:


116

แนวทางที่ดีที่สุดในการแตกตาราง MySQL ที่จะไม่ทำเว้นแต่จะไม่สามารถหลีกเลี่ยงได้โดยสิ้นเชิงที่จะทำ

เมื่อคุณเขียนแอปพลิเคชันคุณมักจะต้องการทำในลักษณะที่เพิ่มความเร็วความเร็วของนักพัฒนา คุณปรับให้เหมาะสมสำหรับเวลาในการตอบสนอง (เวลาจนกว่าคำตอบจะพร้อม) หรือปริมาณงาน (จำนวนคำตอบต่อหน่วยเวลา) เมื่อจำเป็นเท่านั้น

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

กรณีการเขียนคือ a) ความถี่ของการเขียนทำให้เซิร์ฟเวอร์นี้ทำงานหนักเกินไปหรือ b) มีการเขียนมากเกินไปจนทำให้การจำลองแบบล่าช้าอย่างถาวรในลำดับชั้นการจำลองแบบนี้

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

เฉพาะเมื่อคุณต้องแบ่งคุณทำ


ทันทีที่คุณแบ่งคุณจะจ่ายเงินสำหรับสิ่งนั้นในหลายวิธี:

SQL ส่วนใหญ่ของคุณไม่มีการเปิดเผยอีกต่อไป

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

ด้วยสภาพแวดล้อมที่แตกออกคุณอาจรวมตารางบนโหนด A กับข้อมูลบนโหนด B หรือคุณมีตารางที่ใหญ่กว่าโหนดบนโหนด A และ B และกำลังเชื่อมโยงข้อมูลจากข้อมูลนั้นกับข้อมูลที่อยู่บนโหนด B และ C คุณกำลังเริ่มเขียนความละเอียดการรวมที่ใช้แฮชฝั่งแอปพลิเคชันด้วยตนเองเพื่อแก้ไขปัญหานั้น (หรือคุณกำลังสร้างคลัสเตอร์ MySQL ใหม่) ซึ่งหมายความว่าคุณจะมี SQL จำนวนมากที่ไม่ได้ประกาศอีกต่อไป แต่กำลังแสดงฟังก์ชันการทำงานของ SQL ในขั้นตอน (เช่นคุณกำลังใช้คำสั่ง SELECT ในลูป)

คุณมีเวลาแฝงของเครือข่ายจำนวนมาก

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

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

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

คุณกำลังสูญเสียพลังในการแสดงออกของ SQL ไปมาก

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

MySQL ไม่มี API ที่อนุญาตให้มีการสืบค้นแบบอะซิงโครนัสที่อยู่ในลำดับการทำงาน

เมื่อข้อมูลประเภทเดียวกันอยู่ในหลายโหนด (เช่นข้อมูลผู้ใช้บนโหนด A, B และ C) การสืบค้นแนวนอนมักจะต้องได้รับการแก้ไขกับโหนดเหล่านี้ทั้งหมด ("ค้นหาบัญชีผู้ใช้ทั้งหมดที่ไม่ได้เข้าสู่ระบบเป็นเวลา 90 วัน หรือมากกว่า"). เวลาในการเข้าถึงข้อมูลจะเพิ่มขึ้นเป็นเชิงเส้นตามจำนวนโหนดเว้นแต่จะสามารถถามหลายโหนดพร้อมกันได้และผลลัพธ์จะรวมกันเมื่อเข้ามา ("แผนที่ - ลด")

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


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

คำถามมีมากกว่านี้หากคุณต้องการสร้างชาร์ดอัตโนมัติ (การกำหนดว่าแถวใดจะไปยังโหนดใดโดยการแฮชคีย์หลักเป็นต้น) หรือหากคุณต้องการแยกการทำงานด้วยวิธีแมนนวล ("ตารางที่เกี่ยวข้องกับเรื่องราวของผู้ใช้ xyz ไปที่นี้ master ในขณะที่ตารางที่เกี่ยวข้องกับ abc และ def จะไปที่ master นั้น ")

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

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

Functional sharding มีข้อดีคือทำได้ค่อนข้างง่ายกับ codebase ที่มีอยู่โดยมีการเปลี่ยนแปลงจำนวนมากที่ไม่มากเกินไป http://Booking.comได้ทำหลายครั้งในช่วงหลายปีที่ผ่านมาและได้ผลดีสำหรับพวกเขา


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


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

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

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

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

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

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

  3. นี่เหมือนกับ # 2 จริงๆ


dbShards ถูกใช้ในการผลิตที่ไหนบ้าง นอกจากนี้ยังไม่ใช่โอเพ่นซอร์ส
sheki

วิธีที่ 2 และ 3 อาจแตกต่างกันหากพร็อกซีค้นหาโดยอิงตามแฮชแทนที่จะเป็นฐานข้อมูลหรือร้านค้า
sheki

1
dbShards อยู่ในระหว่างการผลิตกับลูกค้าที่หลากหลาย แต่ไม่ใช่มันไม่ใช่โอเพ่นซอร์ส ฉันไม่คิดว่าคุณจะพบกับผลิตภัณฑ์ที่มีการคัดแยกโอเพนซอร์สที่ดี และใช่คุณถูกต้องที่สามารถใช้แฮชเป็นการค้นหาได้ แต่ในกรณีนี้คุณยังคงต้อง "หยุด" อีกครั้งเพื่อให้ธุรกรรมของคุณไปยังฐานข้อมูล นั่นคือเหตุผลที่การแบ่ง "แอปพลิเคชันตระหนัก" มักจะเร็วกว่า
chantheman

แต่อย่างที่บอกถ้าคุณได้แอปพลิเคชั่น Sharding ที่คงความสมบูรณ์ของความสัมพันธ์คุณก็จะมีรูปร่างที่ดี ฉันพูดถึง dbShards เพราะเป็นสิ่งเดียวที่ฉันรู้ และเนื่องจากเป็นเช่นนั้นมันจะปรับขนาดความเร็วในการเขียนและอ่านของคุณในเชิงเส้น คุณเพิ่ม "ชาร์ด" 4 รายการหรือคุณแบ่งเซิร์ฟเวอร์ MySQL หนึ่งเซิร์ฟเวอร์ออกเป็น 4 เซิร์ฟเวอร์และจะทำงานเร็วขึ้น 4 เท่า
chantheman

7

คุณรู้จักโครงการหรือเครื่องมือที่น่าสนใจในพื้นที่นี้หรือไม่?

โครงการใหม่หลายโครงการในพื้นที่นี้:

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/twitter/gizzard/

5

Shard-Queryเป็นโซลูชันการจัดเรียงข้อมูลแบบ OLAP สำหรับ MySQL ช่วยให้คุณสามารถกำหนดการรวมกันของตารางที่แตกและตารางที่ไม่มีการชาร์ต ตารางที่ไม่มีการชาร์ด (เช่นตารางการค้นหา) สามารถเชื่อมต่อกับตารางที่ชาร์ดได้อย่างอิสระและตารางที่ชาร์ดอาจเชื่อมต่อกันได้ตราบใดที่ตารางนั้นเชื่อมโยงกันด้วยคีย์ชาร์ด (ไม่มีส่วนแบ่งส่วนข้ามหรือการรวมตัวเองที่ข้ามขอบเขตของชาร์ด) ในฐานะที่เป็นโซลูชัน OLAP นั้น Shard-Query มักจะมีเวลาตอบสนองขั้นต่ำที่ 100ms หรือน้อยกว่าแม้สำหรับการสืบค้นแบบธรรมดาดังนั้นจึงไม่สามารถใช้ได้กับ OLTP Shard-Query ออกแบบมาเพื่อวิเคราะห์ชุดข้อมูลขนาดใหญ่ควบคู่กัน

OLTP Sharding มีโซลูชันสำหรับ MySQL เช่นกัน การแก้ปัญหาการปิดแหล่งรวมScaleDB , DBShards โซลูชัน OLTP แบบโอเพ่นซอร์ส ได้แก่JetPants , CubridหรือFlock / Gizzard (โครงสร้างพื้นฐานของ Twitter)


3

ระดับการสมัครของหลักสูตร

แนวทางที่ดีที่สุดที่ฉันเคยพบในหนังสือเล่มนี้

MySQL ประสิทธิภาพสูง http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

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

ฉันขอแนะนำให้คุณซื้อและอ่านส่วน "mysql scaling"


หนังสือที่คุณแนะนำมีอายุ 8 ปี ... ครอบคลุมการจัดเรียงข้อมูลที่เกี่ยวข้องกับเทคโนโลยีในปัจจุบันหรือไม่
raffian

1
ครอบคลุมแนวทางพื้นฐานบางประการในการปรับขนาด mysql AFAIK ไม่มีอะไรเปลี่ยนแปลงในการปรับขนาด mysql เทคนิคการชาร์ดดิ้งและการจำลองระดับแอปเดียวกันถูกใช้กันอย่างแพร่หลายในปัจจุบัน
Andrey Frolov

ฉันอาจจะผิด แต่ฉันได้ทำการวิจัยมากมายเกี่ยวกับเรื่องนี้ในช่วงสัปดาห์ที่ผ่านมาและดูเหมือนว่า mySQL จะมีการเปลี่ยนแปลงมากมายในช่วง 8 ปีที่ผ่านมาโดยเฉพาะอย่างยิ่งเกี่ยวกับการแบ่งพาร์ติชันและการแคช มีเวอร์ชันใหม่ที่ออกมาในปีนี้: amazon.com/High-Performance-MySQL-Optimization-Replication/dp/…ฉันยังไม่ได้อ่าน แต่ฉันคิดว่ามันครอบคลุมโมเดลการจำลองแบบใหม่ที่มีอยู่
NateDSaint

4
หนังสือ .. ทำไมไม่อธิบายไว้ที่นี่
DDD

2

ในปี 2018 ดูเหมือนว่าจะมีโซลูชัน MySql-native สำหรับสิ่งนั้น จริงๆแล้วมีอย่างน้อย 2 - InnoDB ClusterและNDB Cluster (มีเวอร์ชันเชิงพาณิชย์และเวอร์ชันชุมชน)

เนื่องจากคนส่วนใหญ่ที่ใช้ MySql community edition คุ้นเคยกับ InnoDB engine มากกว่านี่คือสิ่งที่ควรสำรวจเป็นอันดับแรก รองรับการจำลองแบบและการแบ่งพาร์ติชัน / ชาร์ดนอกกรอบและใช้ MySql Router สำหรับตัวเลือกการกำหนดเส้นทาง / โหลดบาลานซ์ที่แตกต่างกัน

ไวยากรณ์สำหรับการสร้างตารางของคุณจะต้องเปลี่ยนแปลงตัวอย่างเช่น:

    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

(นี่เป็นเพียงหนึ่งในสี่ประเภทการแบ่งพาร์ติชัน )

ข้อ จำกัด ที่สำคัญอย่างหนึ่ง:

คีย์ต่างประเทศ InnoDB และการแบ่งพาร์ติชัน MySQL เข้ากันไม่ได้ ตาราง InnoDB ที่แบ่งพาร์ติชันไม่สามารถมีการอ้างอิงคีย์นอกและไม่สามารถมีคอลัมน์ที่อ้างอิงโดยคีย์ต่างประเทศได้ ตาราง InnoDB ที่มีหรือที่อ้างอิงโดยคีย์นอกไม่สามารถแบ่งพาร์ติชันได้


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