Shopify ha spostato le prenotazioni di inventario su MySQL
Shopify ha spostato il suo sistema di prenotazione dell'inventario da Redis al database MySQL che già conteneva il registro dell'inventario.
Shopify ha spostato il suo sistema di prenotazione dell'inventario da Redis al database MySQL che già conteneva il registro dell'inventario. Un pool limitato di righe di unità bloccabili individualmente consente ai checkout simultanei di utilizzare SKIP LOCKED per selezionare diverse unità idonee. Il design dipende anche dai limiti delle transazioni, dal layout della chiave primaria, dalle regole di rifornimento e dall'osservazione del tempo di mantenimento della connessione tra i checkout.
Leggi l'edizione scritta (inglese) ↗
Contenuto di questo video
- Il vecchio modello di contatore di quantità di Redis gestiva la concorrenza, ma la pulizia delle prenotazioni e l'aggiornamento del registro MySQL non potevano condividere una singola transazione atomica locale.
- Il sostituto utilizza una riga per unità disponibile in un pool limitato a 1.000 per combinazione articolo/località. Un pool vuoto può attivare il rifornimento in linea con richieste concorrenti in attesa dietro un blocco di rifornimento.
- La chiave primaria composita è (shop_id, inventory_item_id, inventory_group_id, id). Shopify ha ridotto l'overhead dei blocchi nel suo prototipo e ha utilizzato READ COMMITTED per evitare blocchi a intervallo che bloccavano il rifornimento.
- La riserva elimina le righe del pool prima di inserire i record di prenotazione. Il commit rilascia i blocchi del database mentre la "hold" memorizzata persiste durante il pagamento; il pagamento riuscito rivendica il registro e rimuove la prenotazione in una successiva transazione atomica.
- MySQL documenta SKIP LOCKED come una vista incoerente che omette le righe bloccate. Non stabilisce un conteggio completo delle scorte o un'equa alternanza, si applica solo ai blocchi a livello di riga ed è insicuro per la replica basata su istruzioni.
- L'esempio sorgente include expires_at, ma Shopify non documenta l'algoritmo di pulizia della scadenza di MySQL. Il ramo di rilascio/scadenza del video è un requisito del ciclo di vita esplicativo.
- Il tempo di mantenimento della connessione in altro codice di checkout è stato l'ultimo collo di bottiglia della produttività. Shopify ha scritto in "shadow" entrambi i sistemi, confrontato i risultati e ha effettuato un passaggio graduale con un fallback di "kill-switch" di Redis.
Trascrizione tradotta
Tradotto dalla narrazione originale inglese. L'audio e i sottotitoli disponibili sono controllati da YouTube.
Perché spostare le prenotazioni su MySQL?
0:00 Un checkout ha bisogno di Redis per rimanere veloce. Shopify ha spostato le prenotazioni di inventario su MySQL utilizzando una riga per unità in un pool limitato. Perché scegliere MySQL? Come si saltano i blocchi in sicurezza? Questo è The Daily Diff, dietro le quinte. E perché le query veloci hanno comunque raggiunto un limite massimo? Shopify è una piattaforma di commercio per vendere online e di persona. Redis è un archivio dati in memoria.
0:21 MySQL è un database relazionale e Shopify teneva già il suo registro dell'inventario lì. Una prenotazione detiene brevemente lo stock mentre un acquirente paga.
Perché due archivi erano rischiosi?
0:29 Il loro modello Redis decrementava un contatore di articoli. La rivendicazione di un ordine pagato significava aggiornare il registro MySQL e pulire Redis. Quelle scritture separate potevano lasciare lo stock venduto due volte o non disponibile quando avrebbe dovuto essere vendibile. Il vecchio modello mancava anche di consapevolezza della posizione. La sostituzione deve scegliere lo stock da un luogo che possa soddisfare l'ordine. Un magazzino nel continente sbagliato rende un'ottima voce di database e una terribile promessa di consegna. I precedenti tentativi con MySQL utilizzavano una riga di quantità, quindi i checkout in competizione si mettevano in coda al
Cosa diventa l'unità bloccabile?
0:56 stesso blocco. Pensa a una corda di velluto intorno a una cella di un foglio di calcolo. L'aggiunta di più lavoratori allunga solo la coda. Shopify ha cambiato l'oggetto bloccabile. Ogni unità disponibile ottiene la propria riga. Una lettura con blocco salta le unità che un'altra transazione detiene e seleziona altre unità idonee. Diversi lavoratori possono acquisire diverse righe, mentre il contatore "caldo" rimane fuori dal loro percorso.
Cosa succede quando il pool si svuota?
1:15 Quel pool è limitato a mille righe per articolo e località. Il rifornimento attinge dal registro. Se si svuota, il percorso di riserva si rifornisce in linea, con richieste concorrenti in attesa dietro un blocco di rifornimento. Pool vuoto non significa magazzino vuoto. La riserva elimina le righe del pool selezionate, quindi inserisce i record di prenotazione in una transazione. Il commit rilascia i blocchi del database.
1:35 Il rollback annulla le modifiche. La prenotazione sopravvive all'elaborazione del pagamento come stato memorizzato. Il pagamento riuscito rivendica il registro e rimuove la prenotazione atomicamente. I blocchi del database non devono mai sorvegliare il modulo di pagamento. La loro chiave primaria composita inizia con negozio, articolo, gruppo, quindi identità dell'unità. La corrispondenza della ricerca ha ridotto il blocco dell'indice nel loro prototipo. Utilizzano anche la lettura commitata per evitare i blocchi a intervallo che bloccavano il rifornimento del pool,
1:57 e un ordine di tabella consistente per prevenire attese circolari. L'esempio pubblicato registra un tempo di scadenza. I pagamenti abbandonati devono rilasciare lo stock eventualmente, o il carrello diventa un proprietario. Il post di Shopify lascia quell'algoritmo di pulizia non specificato, quindi questo diagramma mostra il requisito del ciclo di vita. Ecco il problema.
Cosa tralascia SKIP LOCKED?
2:14 Skip locked esclude le righe bloccate, quindi il manuale chiama il suo risultato una vista incoerente. Non fornisce né un conteggio completo delle scorte né un'equa alternanza. Mantieni la decisione sulla disponibilità e le regole di rifornimento intorno ad essa.
Dov'era il vero limite massimo?
2:26 E quel limite massimo? Altro codice di checkout stava mantenendo le connessioni al database troppo a lungo. Shopify ha etichettato i chiamanti e misurato il tempo di mantenimento della connessione, quindi ha pulito il percorso di checkout e ha rivisto la concorrenza dei thread. Le query veloci possono comunque mettersi in coda fuori dalla query.
Perché dovrei "spedire" questo design?
2:38 Hanno scritto in "shadow" entrambi i sistemi con Redis autorevole, hanno confrontato i risultati, quindi hanno effettuato un passaggio graduale con un "kill switch". Il mio verdetto è SHIP IT. Spedirei il confine di transazione condiviso e quel rollout con rollback, con l'intero percorso di checkout strumentato. Hai una domanda su questo? Mettila nei commenti. E questo è il diff per oggi.
2:54 Sono Niko di Axrisi. Merge responsabilmente.
Fonti
- 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



