Inilipat ng Shopify ang mga reserbasyon ng imbentaryo sa MySQL
Inilipat ng Shopify ang sistema nito ng reserbasyon ng imbentaryo mula sa Redis patungo sa MySQL database na naglalaman na ng ledger ng imbentaryo.
Inilipat ng Shopify ang sistema nito ng reserbasyon ng imbentaryo mula sa Redis patungo sa MySQL database na naglalaman na ng ledger ng imbentaryo. Ang isang hangganang pool ng mga indibidwal na nalo-lock na row ng unit ay nagbibigay-daan sa mga sabay-sabay na checkout na gamitin ang SKIP LOCKED upang pumili ng iba't ibang kwalipikadong unit. Ang disenyo ay nakasalalay din sa mga hangganan ng transaksyon, layout ng primary-key, mga panuntunan sa replenishment at pagmamasid sa oras ng paghawak ng koneksyon sa buong checkout.
Basahin ang nakasulat na edisyon (English) ↗
Ang sakop ng video na ito
- Ang lumang modelo ng Redis na may counter ng dami ay humahawak ng concurrency, ngunit ang paglilinis ng reserbasyon at ang pag-update ng ledger ng MySQL ay hindi maaaring magbahagi ng iisang lokal na atomic na transaksyon.
- Ang kapalit ay gumagamit ng isang row bawat magagamit na unit sa isang pool na may limitasyon na 1,000 bawat kombinasyon ng item/lokasyon. Ang isang walang laman na pool ay maaaring mag-trigger ng inline na replenishment na may sabay-sabay na mga kahilingan na naghihintay sa likod ng isang replenishment lock.
- Ang composite primary key ay (shop_id, inventory_item_id, inventory_group_id, id). Binawasan ng Shopify ang lock overhead sa prototype nito at ginamit ang READ COMMITTED upang maiwasan ang gap locks na humaharang sa replenishment.
- Ang mga reservation ay nagde-delete ng mga row ng pool bago mag-insert ng mga record ng reserbasyon. Ang pag-commit ay nagre-release ng mga lock ng database habang ang naka-store na hold ay nananatili sa kabuuan ng pagbabayad; ang matagumpay na pagbabayad ay nag-aangkin sa ledger at nagtatanggal ng reserbasyon sa isang kalaunan na atomic na transaksyon.
- Dinokumento ng MySQL ang SKIP LOCKED bilang isang hindi magkatugmang view na nagtatanggal ng mga naka-lock na row. Hindi ito nagtatatag ng kumpletong bilang ng stock o patas na pagpapalit ng turn, nalalapat lamang ito sa mga lock na antas ng row at hindi ligtas para sa pagtitiklop na batay sa pahayag.
- Kasama sa halimbawa ng pinagmulan ang expires_at, ngunit hindi idinokumento ng Shopify ang algorithm ng paglilinis ng pag-expire ng MySQL. Ang release/expiry branch ng video ay isang kinakailangan sa paliwanag ng lifecycle.
- Ang oras ng paghawak ng koneksyon sa iba pang checkout code ang huling bottleneck ng throughput. Sumulat ang Shopify ng shadow-write sa parehong sistema, inihambing ang mga resulta at unti-unting lumipat na may fallback na Redis kill-switch.
Isinaling transcript
Isinalin mula sa orihinal na salaysay sa English. Ang available na audio at mga caption ay kinokontrol ng YouTube.
Bakit ilipat ang mga reserbasyon sa MySQL?
0:00 Kailangan ng isang checkout ang Redis upang manatiling mabilis. Inilipat ng Shopify ang mga reserbasyon ng imbentaryo sa MySQL gamit ang isang row bawat unit sa isang may hangganang pool. Bakit pipiliin ang MySQL? Paano mo maiiwasan ang mga lock nang ligtas? Ito ang The Daily Diff, sa ilalim ng hood. At bakit pa rin umabot sa kisame ang mabilis na mga query? Ang Shopify ay isang platform ng commerce para sa pagbebenta online at nang personal. Ang Redis ay isang in-memory data store.
0:21 Ang MySQL ay isang relational database, at pinanatili na ng Shopify ang ledger ng imbentaryo nito doon. Ang isang reserbasyon ay panandaliang nagtatago ng stock habang nagbabayad ang isang mamimili.
Bakit mapanganib ang dalawang tindahan?
0:29 Ang kanilang modelo ng Redis ay nagpapababa ng counter ng item. Ang pag-angkin ng binayaran na order ay nangangahulugang pag-update ng ledger ng MySQL at paglilinis ng Redis. Ang mga hiwalay na pagsusulat na iyon ay maaaring mag-iwan ng stock na nabenta nang dalawang beses o hindi magagamit kapag dapat itong maging nabebenta. Kulang din sa kaalaman sa lokasyon ang lumang modelo. Dapat pumili ang kapalit ng stock mula sa isang lugar na maaaring tumupad sa order. Ang isang bodega sa maling kontinente ay gumagawa ng mahusay na entry sa database at isang kakila-kilabot na pangako sa paghahatid. Ang mga naunang pagtatangka ng MySQL ay gumamit ng isang row ng dami, kaya ang magkakakumpitensyang checkout ay pumila sa
Ano ang magiging lockable unit?
0:56 parehong lock. Isipin ang isang velvet rope sa paligid ng isang cell ng spreadsheet. Ang pagdaragdag ng mas maraming manggagawa ay nagpapahaba lamang ng pila. Binago ng Shopify ang lockable object. Ang bawat magagamit na unit ay may sariling row. Ang isang locking read ay nilalaktawan ang mga unit na hawak ng isa pang transaksyon at pumipili ng iba pang kwalipikadong mga unit. Maaaring makuha ng iba't ibang manggagawa ang iba't ibang row, habang ang mainit na counter ay nananatiling wala sa kanilang landas.
Ano ang mangyayari kapag naubos ang pool?
1:15 Ang pool na iyon ay may limitasyon na isang libong row bawat item at lokasyon. Ang replenishment ay kumukuha mula sa ledger. Kung ito ay maubos, ang reserve path ay nagre-replenish inline, na may magkakakumpitensyang kahilingan na naghihintay sa likod ng isang replenishment lock. Ang walang laman na pool ay hindi nangangahulugang walang laman na bodega. Dine-delete ng reserve ang mga napiling row ng pool, pagkatapos ay nag-i-insert ng mga record ng reserbasyon sa isang transaksyon. Ang commit ay nagre-release ng mga lock ng database.
1:35 Ina-undo ng rollback ang mga pagbabago. Ang reserbasyon ay nananatili sa kabuuan ng pagproseso ng pagbabayad bilang nakaimbak na estado. Ang matagumpay na pagbabayad ay nag-aangkin sa ledger at nagtatanggal ng reserbasyon nang atomically. Hindi kailanman kailangang bantayan ng mga lock ng database ang form ng pagbabayad. Ang kanilang composite primary key ay nagsisimula sa shop, item, grupo, pagkatapos ay identity ng unit. Ang pagtutugma ng lookup ay nagpababa ng index locking sa kanilang prototype. Gumagamit din sila ng read committed upang maiwasan ang mga gap lock na humaharang sa
1:57 replenishment ng pool, at isang pare-parehong order ng table upang maiwasan ang mga pabilog na paghihintay. Ang na-publish na halimbawa ay nagtatala ng oras ng pag-expire. Ang mga inabandunang pagbabayad ay nangangailangan ng stock na ilabas sa kalaunan, o ang shopping cart ay magiging isang landlord. Hindi tinukoy ng post ng Shopify ang algorithm ng paglilinis na iyon, kaya ipinapakita ng diagram na ito ang kinakailangan sa lifecycle. Narito ang catch.
Ano ang iniiwan ng SKIP LOCKED?
2:14 Ang Skip locked ay nagtatanggal ng mga naka-lock na row, kaya tinatawag ng manual ang resulta nito na isang hindi magkatugmang view. Hindi ito nagbibigay ng kumpletong bilang ng stock o patas na pagpapalit ng turn. Panatilihin ang desisyon sa pagkakaroon at mga panuntunan sa replenishment sa paligid nito.
Nasaan ang tunay na kisame?
2:26 At ang kisame na iyon? Ang iba pang checkout code ay humahawak ng mga koneksyon sa database nang masyadong mahaba. Tina-tag ng Shopify ang mga tumatawag at sinusukat ang oras ng paghawak ng koneksyon, pagkatapos ay nilinis ang checkout path at muling binisita ang thread concurrency. Ang mabilis na mga query ay maaari pa ring pumila sa labas ng query.
Bakit ko ipapadala ang disenyong ito?
2:38 Sini-shadow-write nila ang parehong sistema sa Redis authoritative, inihambing ang mga resulta, pagkatapos ay unti-unting lumipat na may kill switch. Ang aking hatol ay SHIP IT. Ipo-SHIP IT ko ang shared transaction boundary at ang rollbackable rollout na iyon, na may instrumentasyon sa buong checkout path. May tanong tungkol dito? Ilagay ito sa mga komento. At iyon ang diff para sa araw na ito.
2:54 Ako si Niko mula sa Axrisi. Mag-merge nang may pananagutan.
Mga Pinagmulan
- We replaced Redis with MySQL for inventory reservations—and it scaledShopify Engineering — Emilie Noel
- Simplified reservation SQL embedded in Shopify's articleShopify Engineering / CourtneySymons on GitHub Gist
- MySQL 8.0 — Locking ReadsOracle / MySQL Reference Manual
- MySQL 8.0 — Transaction Isolation LevelsOracle / MySQL Reference Manual
- What Is Shopify and How Does It Work?Shopify
- Redis quick startsRedis documentation
- What is MySQL?Oracle / MySQL Reference Manual



