Shopify siirsi varastovaraukset MySQLiin
Shopify siirsi varastovarauksensa Redisistä MySQL-tietokantaan, jossa varaston kirjanpito jo oli.
Shopify siirsi varastovarauksensa Redisistä MySQL-tietokantaan, jossa varaston kirjanpito jo oli. Rajattu joukko yksittäin lukittavia yksikkörivejä antaa samanaikaisille kassoille mahdollisuuden käyttää SKIP LOCKED -komentoa valitakseen eri kelvollisia yksiköitä. Suunnittelu riippuu myös transaktiorajoista, ensisijaisen avaimen asettelusta, täydennyssäännöistä ja yhteysajan tarkkailusta koko kassatapahtuman ajan.
Lue kirjoitettu versio (englanniksi) ↗
Mitä tämä video käsittelee
- Vanha Redisin määrälaskurimalli käsitteli rinnakkaisuutta, mutta varauksen puhdistus ja MySQL-kirjanpidon päivitys eivät voineet jakaa yhtä paikallista atomista transaktiota.
- Uusi ratkaisu käyttää yhtä riviä per saatavilla oleva yksikkö poolissa, joka on rajoitettu 1 000:een per tuote/sijaintiyhdistelmä. Tyhjä pooli voi laukaista sisäisen täydennyksen, kun samanaikaiset pyynnöt odottavat täydennyslukon takana.
- Komposiittinen ensisijainen avain on (shop_id, inventory_item_id, inventory_group_id, id). Shopify vähensi lukituksen ylikuormitusta prototyypissään ja käytti READ COMMITTED -tilaa välttääkseen aukkolukituksia, jotka estivät täydennyksen.
- Varaus poistaa poolirivit ennen varaustietueiden lisäämistä. Vahvistus vapauttaa tietokannan lukitukset, kun taas tallennettu pito säilyy maksun ajan; onnistunut maksu kirjaa varaston ja poistaa varauksen myöhemmässä atomisessa transaktiossa.
- MySQL-dokumentaatio kuvaa SKIP LOCKED -komennon epäjohdonmukaisena näkymänä, joka jättää lukitut rivit pois. Se ei anna täydellistä varastotilannetta tai oikeudenmukaista vuoronvaihtoa, se koskee vain rivitason lukituksia ja on turvaton statement-pohjaisessa replikoinnissa.
- Lähde-esimerkki sisältää expires_at-kentän, mutta Shopify ei dokumentoi MySQL:n vanhenemisen puhdistusalgoritmia. Videon release/expiry-haara on selittävä elinkaarivaatimus.
- Yhteyden pitkä kesto muussa kassakoodissa oli viimeinen suorituskyvyn pullonkaula. Shopify kirjoitti molempiin järjestelmiin rinnakkain, vertasi tuloksia ja vaihtoi asteittain Redisin "kill-switch"-palautusmekanismin kanssa.
Käännetty transkriptio
Käännetty alkuperäisestä englanninkielisestä selostuksesta. Käytettävissä olevan äänen ja tekstitysten hallinta tapahtuu YouTuben kautta.
Miksi varaukset siirrettiin MySQLiin?
0:00 Kassa tarvitsee Redisin pysyäkseen nopeana. Shopify siirsi varastovaraukset MySQLiin käyttäen yhtä riviä per yksikkö rajatussa poolissa. Miksi valita MySQL? Miten lukitukset ohitetaan turvallisesti? Tämä on The Daily Diff, kulissien takana. Ja miksi nopeat kyselyt osuivat silti kattoon? Shopify on kaupankäyntialusta verkkokauppaan ja kivijalkamyyntiin. Redis on muistissa oleva tietovarasto.
0:21 MySQL on relaatiotietokanta, ja Shopify säilytti jo varastokirjanpitonsa siellä. Varaus pitää varaston lyhyesti, kun ostaja maksaa.
Miksi kaksi varastoa oli riskialtista?
0:29 Heidän Redis-mallinsa vähensi nimikkeen laskuria. Maksetun tilauksen kirjaaminen tarkoitti MySQL-kirjanpidon päivittämistä ja Redisin puhdistamista. Nämä erilliset kirjoitukset saattoivat jättää varaston myydyksi kahdesti tai saatavilla olevaksi, vaikka sen pitäisi olla myytävänä. Vanha malli ei myöskään huomioinut sijaintia. Uuden ratkaisun on valittava varasto jostakin, joka voi täyttää tilauksen. Väärällä mantereella oleva varasto on erinomainen tietokantamerkintä ja hirveä toimituslupaus. Aikaisemmat MySQL-yritykset käyttivät määräriviä, joten kilpailevat kassat jonottivat samaan
Mikä on lukittava yksikkö?
0:56 lukkoon. Ajattele samettiköyttä taulukkolukon ympärillä. Useamman työntekijän lisääminen vain pidentää jonoa. Shopify muutti lukittavaa objektia. Jokaisella saatavilla olevalla yksiköllä on oma rivinsä. Lukittava luku ohittaa yksiköt, jotka toinen transaktio pitää hallussaan, ja valitsee muut kelvolliset yksiköt. Eri työntekijät voivat hankkia eri rivejä, samalla kun kuuma laskuri pysyy poissa heidän tieltään.
Mitä tapahtuu, kun pooli tyhjenee?
1:15 Tämä pooli on rajattu tuhanteen riviin per tuote ja sijainti. Täydennys nostaa varastosta. Jos se tyhjenee, varaus polku täydentää sisäisesti, kilpailevien pyyntöjen odottaessa täydennyslukon takana. Tyhjä pooli ei tarkoita tyhjää varastoa. Varaus poistaa valitut poolirivit ja lisää sitten varaustietueet transaktiossa. Vahvistus vapauttaa tietokannan lukitukset.
1:35 Palautus kumoaa muutokset. Varaus säilyy maksun käsittelyn ajan tallennettuna tilana. Onnistunut maksu kirjaa varaston ja poistaa varauksen atomisesti. Tietokannan lukitusten ei tarvitse koskaan vartioida maksulomaketta. Niiden komposiittinen ensisijainen avain alkaa kaupalla, tuotteella, ryhmällä ja sitten yksikön tunnisteella. Haun vastaavuus vähensi indeksilukitusta heidän prototyypissään. He käyttävät myös READ COMMITTED -tilaa välttääkseen aukkolukituksia, jotka estivät poolin
1:57 täydennyksen, ja yhtenäistä taulukkujärjestystä estääkseen pyöreitä odotuksia. Julkaistu esimerkki tallentaa vanhenemisajan. Hylätyt maksut tarvitsevat varaston vapauttamista lopulta, tai ostoskorista tulee vuokranantaja. Shopifyn postaus jättää tämän puhdistusalgoritmin täsmentämättä, joten tämä kaavio näyttää elinkaarivaatimuksen. Tässä on se jippo.
Mitä SKIP LOCKED jättää pois?
2:14 SKIP LOCKED jättää lukitut rivit pois, joten käsikirja kutsuu sen tulosta epäjohdonmukaiseksi näkymäksi. Se ei tarjoa täydellistä varastotilannetta eikä reilua vuoronvaihtoa. Pidä saatavuuspäätös ja täydennyssäännöt sen ympärillä.
Missä oli todellinen katto?
2:26 Entä se katto? Muu kassakoodi piti tietokantayhteyksiä auki liian kauan. Shopify merkkasi kutsujat ja mittasi yhteyden pitoajan, sitten siisti kassapolun ja tarkasteli uudelleen säikeiden rinnakkaisuutta. Nopeat kyselyt voivat silti jonottaa kyselyn ulkopuolella.
Miksi ottaisin tämän suunnittelun käyttöön?
2:38 He kirjoittivat molempiin järjestelmiin rinnakkain Redisin ollessa auktoritatiivinen, vertasivat tuloksia ja vaihtoivat asteittain "kill switch" -kytkimellä. Minun tuomioni on SHIP IT. Lähettäisin jaetun transaktiorajan ja sen palautettavan käyttöönoton, koko kassapolun instrumentoituna. Onko sinulla kysyttävää tästä? Laita se kommentteihin. Ja tämä on tämän päivän ero.
2:54 Olen Niko Axrisista. Yhdistä vastuullisesti.
Lähteet
- 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



