Shopify heeft voorraadreserveringen verplaatst naar MySQL
Shopify heeft zijn voorraadreserveringssysteem van Redis naar de MySQL-database verplaatst, die de voorraadadministratie al bevatte.
Shopify heeft zijn voorraadreserveringssysteem van Redis naar de MySQL-database verplaatst, die de voorraadadministratie al bevatte. Een begrensde pool van individueel vergrendelbare eenheidsrijen stelt gelijktijdige checkouts in staat om SKIP LOCKED te gebruiken om verschillende in aanmerking komende eenheden te selecteren. Het ontwerp is ook afhankelijk van transactiegrenzen, de lay-out van de primaire sleutel, aanvullingsregels en het observeren van de verbindingstijd tijdens het afrekenproces.
Lees de geschreven editie (Engels) ↗
Wat deze video behandelt
- Het oude Redis-model met kwantiteitstellers kon omgaan met gelijktijdigheid, maar het opschonen van reserveringen en de update van de MySQL-administratie konden geen enkele lokale atomaire transactie delen.
- De vervanging maakt gebruik van één rij per beschikbare eenheid in een pool die is afgetopt op 1.000 per item/locatiecombinatie. Een lege pool kan inline aanvulling activeren, waarbij gelijktijdige verzoeken wachten achter een aanvullingsslot.
- De samengestelde primaire sleutel is (shop_id, inventory_item_id, inventory_group_id, id). Shopify verminderde de overhead van sloten in zijn prototype en gebruikte READ COMMITTED om gap locks te vermijden die aanvulling blokkeerden.
- Reserveringen verwijderen poolrijen voordat reserveringsrecords worden ingevoegd. Commit vrijgeeft databaselocks terwijl de opgeslagen hold blijft bestaan tijdens de betaling; succesvolle betaling claimt de administratie en verwijdert de reservering in een latere atomaire transactie.
- MySQL documenteert SKIP LOCKED als een inconsistente weergave die vergrendelde rijen overslaat. Het legt geen volledige voorraad vast of eerlijke beurtverdeling, is alleen van toepassing op rij-niveau locks en is onveilig voor op statements gebaseerde replicatie.
- Het bronvoorbeeld bevat expires_at, maar Shopify documenteert het MySQL-verval-opschoonalgoritme niet. De release/expiry-tak van de video is een verklarende levenscyclusvereiste.
- De verbindingstijd in andere checkoutcode was de uiteindelijke doorvoerknelpunt. Shopify schreef beide systemen shadow-wise, vergeleek de resultaten en schakelde geleidelijk over met een Redis kill-switch fallback.
Vertaald transcript
Vertaald vanuit de originele Engelse gesproken tekst. Beschikbare audio en ondertiteling worden beheerd door YouTube.
Waarom reserveringen verplaatsen naar MySQL?
0:00 Een checkout heeft Redis nodig om snel te blijven. Shopify verplaatste voorraadreserveringen naar MySQL met één rij per eenheid in een begrensde pool. Waarom kiezen voor MySQL? Hoe sla je locks veilig over? Dit is The Daily Diff, achter de schermen. En waarom bereikten snelle queries nog steeds een plafond? Shopify is een handelsplatform voor online en persoonlijke verkoop. Redis is een in-memory datastore.
0:21 MySQL is een relationele database, en Shopify hield zijn voorraadadministratie al daar. Een reservering houdt kortstondig voorraad vast terwijl een koper betaalt.
Waarom waren twee winkels riskant?
0:29 Hun Redis-model verminderde een itemteller. Het claimen van een betaalde bestelling betekende het bijwerken van de MySQL-administratie en het opschonen van Redis. Die afzonderlijke schrijfacties konden ertoe leiden dat voorraad twee keer werd verkocht of niet beschikbaar was terwijl het wel verkoopbaar moest zijn. Het oude model miste ook locatiebewustzijn. De vervanging moet voorraad kiezen van ergens waar de bestelling kan worden uitgevoerd. Een magazijn op het verkeerde continent is een uitstekende database-ingang en een vreselijke leveringsbelofte. Eerdere MySQL-pogingen gebruikten een kwantiteitsrij, dus concurrerende checkouts stonden in de rij bij hetzelfde
Wat wordt de vergrendelbare eenheid?
0:56 slot. Denk aan een fluwelen touw rond een spreadsheetcel. Het toevoegen van meer werknemers verlengt alleen de wachtrij. Shopify heeft het vergrendelbare object gewijzigd. Elke beschikbare eenheid krijgt zijn eigen rij. Een vergrendelende leesactie slaat eenheden over die een andere transactie vasthoudt en selecteert andere in aanmerking komende eenheden. Verschillende werknemers kunnen verschillende rijen verkrijgen, terwijl de 'hete' teller uit hun weg blijft.
Wat gebeurt er als de pool leeg raakt?
1:15 Die pool is begrensd op duizend rijen per item en locatie. Aanvulling komt uit de administratie. Als het leeg raakt, vult het reservepad inline aan, waarbij concurrerende verzoeken wachten achter een aanvullingsslot. Lege pool betekent geen leeg magazijn. Reserve verwijdert geselecteerde poolrijen en voegt vervolgens reserveringsrecords in een transactie. Commit geeft de databaselocks vrij. Rollback maakt de wijzigingen ongedaan.
1:35 De reservering overleeft de betalingsverwerking als opgeslagen status. Succesvolle betaling claimt de administratie en verwijdert de reservering atomair. Databaselocks hoeven nooit het betaalformulier in de gaten te houden. Hun samengestelde primaire sleutel begint met shop, item, groep, vervolgens eenheidsidentiteit. Het matchen van de lookup verminderde indexvergrendeling in hun prototype. Ze gebruiken ook 'read committed' om de 'gap locks' te vermijden die de aanvulling van de pool blokkeerden, en een consistente tabelvolgorde om circulaire wachttijden te voorkomen. Het gepubliceerde voorbeeld registreert een vervaldatum.
1:57 Verlaten betalingen moeten uiteindelijk voorraad vrijgeven, anders wordt de winkelwagen een verhuurder. Shopify's bericht laat dat opschoonalgoritme ongespecificeerd, dus dit diagram toont de levenscyclusvereiste. Dit is het addertje onder het gras. Skip locked sluit vergrendelde rijen uit, dus de handleiding noemt het resultaat een inconsistente weergave. Het biedt noch een volledige voorraad telling, noch een eerlijke beurtverdeling.
Wat laat SKIP LOCKED buiten beschouwing?
2:14 Houd de beschikbaarheidsbeslissing en aanvullingsregels eromheen. En dat plafond? Andere afrekeningscode hield databaseverbindingen te lang vast.
Waar lag het echte plafond?
2:26 Shopify tagde bellers en mat de verbindingstijd, en ruimde vervolgens het afrekenpad op en herzag de gelijktijdigheid van threads. Snelle queries kunnen nog steeds buiten de query in de wachtrij staan. Ze schaduwden beide systemen met Redis als gezaghebbend, vergeleken de resultaten, en schakelden vervolgens geleidelijk over met een kill switch.
Waarom zou ik dit ontwerp uitrollen?
2:38 Mijn oordeel is: SCHIP HET. Ik zou de gedeelde transactiegrens en die rollbackable uitrol verzenden, met het hele afrekenpad geïnstrumenteerd. Heeft u hier een vraag over? Zet het in de reacties. En dat is de 'diff' voor vandaag. Ik ben Niko van Axrisi. Verantwoord samenvoegen.
2:54 Ik ben Niko van Axrisi. Verantwoord samenvoegen.
Bronnen
- 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



