+− THE DAILY DIFFdev & AI news
SHIP IT

Shopify ย้ายการจองสินค้าคงคลังไปที่ MySQL

Shopify ย้ายระบบการจองสินค้าคงคลังจาก Redis ไปยังฐานข้อมูล MySQL ซึ่งเป็นที่จัดเก็บข้อมูลบัญชีสินค้าคงคลังอยู่แล้ว กลุ่มแถวของหน่วยที่สามารถล็อกได้ทีละรายการในขอบเขตที่กำหนดช่วยให้การชำระเงินที่เกิดขึ้นพร้อมกันสามารถใช้ SKIP LOCKED เพื่อเลือกหน่วยที่เหมาะสมที่แตกต่างกันได้ การออกแบบนี้ยังขึ้นอยู่กับขอบเขตของธุรกรรม, โครงสร้างคีย์หลัก, กฎการเติมสินค้า และการสังเกตระยะเวลาการถือครองการเชื่อมต่อตลอดกระบวนการชำระเงิน

Shopify ย้ายระบบการจองสินค้าคงคลังจาก Redis ไปยังฐานข้อมูล MySQL ซึ่งเป็นที่จัดเก็บข้อมูลบัญชีสินค้าคงคลังอยู่แล้ว กลุ่มแถวของหน่วยที่สามารถล็อกได้ทีละรายการในขอบเขตที่กำหนดช่วยให้การชำระเงินที่เกิดขึ้นพร้อมกันสามารถใช้ SKIP LOCKED เพื่อเลือกหน่วยที่เหมาะสมที่แตกต่างกันได้ การออกแบบนี้ยังขึ้นอยู่กับขอบเขตของธุรกรรม, โครงสร้างคีย์หลัก, กฎการเติมสินค้า และการสังเกตระยะเวลาการถือครองการเชื่อมต่อตลอดกระบวนการชำระเงิน

อ่านฉบับลายลักษณ์อักษร (ภาษาอังกฤษ) ↗

วิดีโอนี้ครอบคลุมอะไรบ้าง

  • โมเดลตัวนับปริมาณของ Redis เดิมสามารถจัดการกับการทำงานพร้อมกันได้ แต่การล้างการจองและการอัปเดตบัญชี MySQL ไม่สามารถแชร์ธุรกรรมอะตอมมิคในเครื่องเดียวกันได้
  • การเปลี่ยนมาใช้หนึ่งแถวต่อหนึ่งหน่วยที่พร้อมใช้งานในกลุ่มที่จำกัดสูงสุด 1,000 แถวต่อชุดค่าผสมของสินค้า/สถานที่ การที่กลุ่มว่างเปล่าสามารถกระตุ้นการเติมสินค้าแบบอินไลน์ได้ โดยคำขอที่เกิดขึ้นพร้อมกันจะรออยู่เบื้องหลังการล็อกการเติมสินค้า
  • คีย์หลักแบบคอมโพสิตคือ (shop_id, inventory_item_id, inventory_group_id, id) Shopify ลดโอเวอร์เฮดของการล็อกในโปรโตไทป์และใช้ READ COMMITTED เพื่อหลีกเลี่ยง gap locks ที่บล็อกการเติมสินค้า
  • การจองจะลบแถวในกลุ่มก่อนที่จะแทรกบันทึกการจอง การคอมมิตจะปล่อยการล็อกฐานข้อมูลในขณะที่การถือครองที่เก็บไว้ยังคงอยู่หลังจากการชำระเงิน การชำระเงินที่สำเร็จจะอ้างสิทธิ์ในบัญชีและลบการจองในธุรกรรมอะตอมมิคในภายหลัง
  • MySQL ระบุว่า SKIP LOCKED เป็นมุมมองที่ไม่สอดคล้องกันที่ละเว้นแถวที่ถูกล็อก ไม่ได้สร้างการนับสต็อกที่สมบูรณ์หรือการหมุนเวียนที่เป็นธรรม ใช้ได้กับการล็อกระดับแถวเท่านั้นและไม่ปลอดภัยสำหรับการจำลองแบบตามคำสั่ง
  • ตัวอย่างต้นฉบับมี expires_at แต่ Shopify ไม่ได้ระบุอัลกอริทึมการล้างข้อมูลหมดอายุของ MySQL สาขาการปล่อย/หมดอายุของวิดีโอเป็นข้อกำหนดวงจรชีวิตเพื่อการอธิบาย
  • ระยะเวลาการถือครองการเชื่อมต่อในโค้ดการชำระเงินอื่น ๆ เป็นคอขวดสุดท้ายของปริมาณงาน Shopify ทำการเขียนเงา (shadow-wrote) ทั้งสองระบบ เปรียบเทียบผลลัพธ์และเปลี่ยนผ่านอย่างค่อยเป็นค่อยไปด้วยสวิตช์ปิด Redis

บทถอดเสียงที่แปลแล้ว

แปลจากการบรรยายภาษาอังกฤษต้นฉบับ เสียงและคำบรรยายที่มีให้จะควบคุมโดย YouTube

ทำไมต้องย้ายการจองไปที่ MySQL?

0:00 การชำระเงินต้องการให้ Redis รวดเร็วอยู่เสมอ Shopify ย้ายการจองสินค้าคงคลังไปที่ MySQL โดยใช้หนึ่งแถวต่อหนึ่งหน่วยใน กลุ่มที่จำกัด ทำไมถึงเลือก MySQL? คุณจะข้ามการล็อกได้อย่างปลอดภัยได้อย่างไร? นี่คือ The Daily Diff, เบื้องหลัง แล้วทำไมคำสั่งค้นหาที่รวดเร็วยังคงชนเพดาน? Shopify เป็นแพลตฟอร์มอีคอมเมิร์ซสำหรับการขายออนไลน์และหน้าร้าน Redis เป็นฐานข้อมูลในหน่วยความจำ

0:21 MySQL เป็นฐานข้อมูลเชิงสัมพันธ์ และ Shopify ได้เก็บข้อมูลบัญชีสินค้าคงคลังไว้ ที่นั่นอยู่แล้ว การจองจะกักตุนสินค้าไว้ชั่วคราวขณะที่ผู้ซื้อชำระเงิน

ทำไมร้านค้าสองแห่งถึงมีความเสี่ยง?

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

หน่วยที่ล็อกได้กลายเป็นอะไร?

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

จะเกิดอะไรขึ้นเมื่อกลุ่มว่างเปล่า?

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

1:35 การย้อนกลับจะยกเลิกการเปลี่ยนแปลง การจองจะยังคงอยู่หลังจากการประมวลผลการชำระเงินในสถานะที่จัดเก็บไว้ การชำระเงินที่สำเร็จจะอ้างสิทธิ์ในบัญชีและลบการจองแบบอะตอมมิค การล็อกฐานข้อมูลไม่จำเป็นต้องดูแลแบบฟอร์มการชำระเงิน คีย์หลักแบบคอมโพสิตของพวกเขาเริ่มต้นด้วยร้านค้า, สินค้า กลุ่ม, แล้วตามด้วยรหัสหน่วย การจับคู่การค้นหาช่วยลดการล็อกดัชนีในโปรโตไทป์ของพวกเขา พวกเขายังใช้ read committed เพื่อหลีกเลี่ยง gap locks ที่บล็อกการเติมสินค้าในกลุ่ม

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

SKIP LOCKED ละเว้นอะไรไปบ้าง?

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

ขีดจำกัดที่แท้จริงอยู่ที่ไหน?

2:26 แล้วเพดานนั้นล่ะ? โค้ดการชำระเงินอื่นกำลังถือการเชื่อมต่อฐานข้อมูลนานเกินไป Shopify ติดแท็กผู้เรียกและวัดระยะเวลาการถือครองการเชื่อมต่อ จากนั้นจึงทำความสะอาดเส้นทางการชำระเงินและตรวจสอบการทำงานพร้อมกันของเธรดอีกครั้ง การค้นหาที่รวดเร็วยังสามารถเข้าคิวนอกการค้นหาได้

ทำไมฉันถึงจะส่งมอบการออกแบบนี้?

2:38 พวกเขาเขียนเงาทั้งสองระบบโดยให้ Redis เป็นผู้มีอำนาจ เปรียบเทียบผลลัพธ์ แล้วสลับไปทีละน้อยด้วยสวิตช์ปิด คำตัดสินของฉันคือ SHIP IT ฉันจะจัดส่งขอบเขตธุรกรรมที่ใช้ร่วมกันและการเปิดตัวที่สามารถย้อนกลับได้นั้น โดยมีเส้นทางการชำระเงินทั้งหมดที่ได้รับการตรวจสอบ มีคำถามเกี่ยวกับเรื่องนี้หรือไม่? ใส่ไว้ในความคิดเห็น และนั่นคือความแตกต่างสำหรับวันนี้

2:54 ฉันชื่อ Niko จาก Axrisi รวมอย่างรับผิดชอบ

แหล่งที่มา

  1. We replaced Redis with MySQL for inventory reservations—and it scaledShopify Engineering — Emilie Noel
  2. Simplified reservation SQL embedded in Shopify's articleShopify Engineering / CourtneySymons on GitHub Gist
  3. MySQL 8.0 — Locking ReadsOracle / MySQL Reference Manual
  4. MySQL 8.0 — Transaction Isolation LevelsOracle / MySQL Reference Manual
  5. What Is Shopify and How Does It Work?Shopify
  6. Redis quick startsRedis documentation
  7. What is MySQL?Oracle / MySQL Reference Manual

วิดีโอที่เกี่ยวข้อง

under-the-hood · th · 11 ต.ค. 2569

Stripe จดจำคำขอของคุณเมื่อการตอบกลับหายไป

การหมดเวลาอาจทำให้การชำระเงินไม่แน่นอนหลังจากที่เซิร์ฟเวอร์ดำเนินการเสร็จสิ้น คำอธิบาย Under the Hood นี้ใช้สัญญา idempotency ที่บันทึกไว้ของ Stripe API v1 เพื่อแสดงคีย์การทำงานที่เสถียร การเล่นซ้ำการ

2:54 ↗
under-the-hood · th · 24 ก.ย. 2569

SAML, เจาะลึก: ลายเซ็นต์ภายในจดหมาย

SAML ทำให้คุณสามารถเข้าสู่ระบบแอปทำงานเกือบทุกแอป และลายเซ็นต์ของมันอาศัยอยู่ภายใน XML ที่มันลงนาม เจาะลึก: การเต้นรำของการเข้าสู่ระบบระหว่างแอป, เบราว์เซอร์ และผู้ให้บริการระบุตัวตน, ลักษณะของ Assert

3:02 ↗
under-the-hood · th · 23 ก.ย. 2569

เมื่อโมเดลตาย ภายใต้กลไกการทำงาน

โมเดล AI ไม่ได้ตาย — มันได้รับวันปิดตัว และเช้าวันรุ่งขึ้น การเรียก API ของคุณจะส่งคืน 404: "โมเดลนี้เลิกใช้งานแล้ว เรียนรู้เพิ่มเติมที่นี่" ภายใต้กลไกการทำงาน: กระบวนการสี่สถานะ (active → legacy → de

3:15 ↗
under-the-hood · th · 21 ก.ย. 2569

Claude แยกตัวประกอบ RSA-896 นี่คือวิธีที่ RSA ถูกทำลายจริง ๆ

เมื่อวันที่ 19 กันยายน วิศวกรของ Anthropic ได้แยกตัวประกอบ RSA-896 ซึ่งเป็นหมายเลขท้าทาย 270 หลัก ด้วย Claude ซึ่งเป็นพอร์ต GPU ของตะแกรง CADO-NFS แบบโอเพนซอร์ส และใช้ GPU ประมาณ 30 ปี บน GPU ที่ไม่ได

3:39 ↗