Come progettare un negozio per evitare l'inventario di overselling (scenario del database distribuito)

7

Al momento disponiamo di un sistema di vendita / acquisto che utilizza un singolo database. Abbiamo prodotti con un campo per il numero che abbiamo nell'inventario (diciamo 100 widget). Abbiamo una tabella clienti. Quando qualcuno aggiunge un widget al carrello, inseriamo un record in una tabella di join tra il cliente e il prodotto che rappresenta l'intenzione di acquistare. Tale record customer_product ha uno stato che indica che è nel carrello o che l'acquisto è stato completato ("In sospeso", "Acquistato").

Quando una richiesta cliente colpisce il sistema per aggiungere un prodotto al proprio carrello, contiamo il numero di record customer_product acquistati e in sospeso per quel prodotto e lo si disabilita se il numero è uguale al totale (100). In questo modo, ci assicuriamo che non consentiamo a 101 persone di avere 100 articoli.

Il database è il collo di bottiglia del nostro sistema e la tabella dei join viene colpita molto. Sospetto che i blocchi di riga e pagina influenzino le prestazioni sotto carico. Immagino che sistemi come Amazon / eBay debbano avere un'architettura db distribuita, e tuttavia in qualche modo gestire il problema di 2 persone che vogliono mettere l'ultimo oggetto nel loro carrello allo stesso tempo. Mi piacerebbe rearchitect il nostro negozio / carrello per alleviare il vincolo db.

Con un singolo database, possiamo fare qualcosa nella nostra clausola WHERE inserto record di join per includere un conteggio delle subquery in modo che se due transazioni di db stanno cercando di fare "l'ultimo widget" inserire contemporaneamente che qualsiasi tentativo di commit secondo fallirà perché il conteggio lo impedirà dopo che la penultima transazione prende l'ultimo widget e cambia il conteggio. Ma in un database distribuito, suppongo che quel trucco non funzionerà.

Quali principi guida o schemi generali dell'architettura di sistema si applicano quando si affrontano tali sfide di concorrenza e risorse condivise in un sistema distribuito?

Nota: sono a conoscenza di domande simili (come Best practice per gestire la concorrenza in un paniere in un sito di e-commerce ). Questa domanda riguarda specificamente come gestirlo in un'architettura distribuita dove ogni istanza di db ha una copia delle tabelle e cambia in un propogate agli altri solo ogni tanto (almeno così è come la immagino - non ho effettivamente impostato su un sistema db distribuito prima).

    
posta jinglesthula 13.01.2017 - 19:39
fonte

2 risposte

12

Dipende dal widget.

Se il widget è raro e costoso (esattamente 10 Ferrari), l'approccio che stai seguendo è corretto. Ovviamente, devi anche tenere conto dell'inventario che viene restituito ma non è stato ancora rifornito, l'inventario che è disponibile per la riparazione, ecc.

Se il widget è un po 'più comune (5.000 chiavi), l'approccio abituale è:

  • Accetta tutti gli ordini. Va benissimo che 5.500 persone ordinino le tue chiavi. Quando arriva il momento di spedirli, ne verranno spediti 5.000 e il resto sarà messo in ordine arretrato. Generalmente il volume degli ordini sarà così basso che non avrai bisogno di un database distribuito.
  • Definisci un trigger "quantità bassa" insieme a un importo di riordino. Ad esempio, potresti avere una regola che dice "ogni volta che il numero di chiavi a mano scende sotto 1.000, chiama il fornitore e ordina altri 5.000". Questa regola è raramente automatizzata: è meglio che il sistema invii una notifica a un essere umano per prendere la decisione finale.
risposta data 13.01.2017 - 19:51
fonte
5

Puoi utilizzare un database separato per gli utenti con i loro carrelli piuttosto che per i riscontri di inventario, utilizzando semplici ID invece di chiavi esterne e creando i requisiti non nulli dell'applicazione.

Questo ridurrà alcuni conflitti rispetto a un singolo database.

Il database di inventario può memorizzare il numero totale di inventario disponibile per ciascun articolo e anche in quel database di inventario (come suggerito) memorizzare / memorizzare il valore calcolato che è il conteggio totale richiesto dal carrello da tutti gli utenti / carrelli database, che dovrà essere aggiornato in quanto gli articoli vengono rivendicati / rilasciati dai carrelli.

Questo ridurrà un po 'di carico sul database dell'utente / carrello a scapito della gestione del valore memorizzato nella cache dall'applicazione (caching / denormalizzato per le prestazioni).

Sia il database utente / carrello che il database di inventario possono essere sottoposti a in numerosi database.

Sharding memorizza le stesse tabelle in più database, anche se non gli stessi dati, in quanto scelte in modo specifico diverse righe vanno in ognuno dei database per diffondere i vari carichi di accesso e di modifica su tali database. Sharding funziona bene per cose come utenti e inventari che non devono essere tutti accessibili contemporaneamente / nella stessa query (non è spesso necessario interrogare tutti gli utenti (ad esempio il conteggio di tutti gli utenti) o tutti gli articoli di inventario allo stesso tempo, es. totale di tutti gli inventari).

Se la strategia di sharding è semplice (ad esempio per l'inventario, l'ID di inventario modulo il numero di frammenti), è relativamente facile identificare quale frammento di inventario ha quell'articolo di inventario.

La combinazione di quanto sopra dovrebbe ridurre significativamente la contesa per i servizi di database.

Ortogonale ad alcuni dei precedenti, puoi anche distribuire il numero di inventario tra le repliche di inventario, dove se hai 5000 widget e 2 repliche, a ognuno viene dato un conteggio di 2500 da vendere.

Non è necessario alcun coordinamento fino a quando non viene raggiunta una soglia minima (ad esempio una replica vende 2400 e ora scende a 100).

A quel punto, il sistema potrebbe richiedere un ribilanciamento dell'inventario dall'altra replica, quindi se l'altra replica ne ha ancora 2000, allora metà potrebbe essere presa dall'altro.

La replica / distribuzione del metodo di inventario può essere combinata con il metodo sharding, in quanto le repliche possono essere ridotte.

    
risposta data 13.01.2017 - 23:21
fonte