Redis เป็นแบบเธรดเดี่ยวแล้วจะทำอย่างไรพร้อมกัน I / O?


170

พยายามที่จะเข้าใจพื้นฐานบางส่วนของ Redis ฉันมาข้ามที่น่าสนใจโพสต์บล็อก

ผู้เขียนฯ :

Redis เป็นแบบเธรดเดี่ยวที่มี epoll / kqueue และสเกลแบบไม่มีกำหนดในแง่ของ I / O concurrency

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

มีใครช่วยอธิบายปัญหานี้หน่อยได้ไหม?

คำตอบ:


360

มันขึ้นอยู่กับว่าคุณนิยามภาวะพร้อมกันได้อย่างไร

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

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

คำถามนี้มีการถกเถียงกันที่นี่: อะไรคือความแตกต่างระหว่างการเกิดพร้อมกันและการขนาน

ดูเพิ่มเติมการนำเสนอนี้จาก Rob Pike

โปรแกรมแบบเธรดเดียวสามารถให้การพร้อมกันที่ระดับ I / O ได้อย่างแน่นอนโดยใช้กลไกมัลติเพล็กซิ่ง I / O (de) และห่วงเหตุการณ์ (ซึ่งเป็นสิ่งที่ Redis ทำ)

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

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


135
การเปรียบเทียบบาร์เทนเดอร์ที่ดี :)
Sergio Tulentsev

3
v4 เป็นผู้เปลี่ยนเกมในแง่นี้ - ดูคำตอบของฉันได้ที่stackoverflow.com/a/45374864/3160475 :)
Itamar Haber

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

ยังคงใช้ได้ในปี 2020?
Roberto Manfreda

21

ตกลง, Redis เป็นเธรดเดี่ยวที่ระดับผู้ใช้, OTOH, I / O แบบอะซิงโครนัสทั้งหมดได้รับการสนับสนุนโดยกลุ่มเธรดเคอร์เนลและ / หรือไดรเวอร์ระดับแยก

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

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


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