So che ci sono domande simili qui, ma mi stanno dicendo di tornare ai normali sistemi RDBMS se ho bisogno di transazioni o uso operazioni atomiche o commit a due fasi . La seconda soluzione sembra la scelta migliore. Il terzo che non desidero seguire perché sembra che molte cose potrebbero andare storte e non posso provarlo in tutti gli aspetti. Sto facendo fatica a riformattare il mio progetto per eseguire operazioni atomiche. Non so se questo provenga dal mio punto di vista limitato (finora ho lavorato solo con i database SQL) o se in realtà non è possibile farlo.
Vorremmo testare MongoDB presso la nostra azienda. Abbiamo scelto un progetto relativamente semplice: un gateway SMS. Consente al nostro software di inviare messaggi SMS alla rete cellulare e il gateway fa il lavoro sporco: in realtà comunica con i provider tramite diversi protocolli di comunicazione. Il gateway gestisce anche la fatturazione dei messaggi. Ogni cliente che richiede il servizio deve acquistare alcuni crediti. Il sistema riduce automaticamente il saldo dell'utente quando viene inviato un messaggio e nega l'accesso se il saldo è insufficiente. Anche perché siamo clienti di fornitori di SMS di terze parti, potremmo anche avere i nostri saldi con loro. Dobbiamo tenere traccia anche di quelli.
Ho iniziato a pensare a come posso archiviare i dati richiesti con MongoDB se riduco la complessità (fatturazione esterna, invio di SMS in coda). Provenendo dal mondo SQL, vorrei creare una tabella separata per gli utenti, un'altra per i messaggi SMS e una per la memorizzazione delle transazioni relative al saldo degli utenti. Diciamo che creo raccolte separate per tutti quelli in MongoDB.
Immagina un'attività di invio di SMS con i seguenti passaggi in questo sistema semplificato:
controlla se l'utente ha un equilibrio sufficiente; negare l'accesso se non c'è credito sufficiente
inviare e archiviare il messaggio nella raccolta SMS con i dettagli e i costi (nel sistema live il messaggio avrebbe un
status
attributo e un'attività lo prenderebbe per la consegna e fisserebbe il prezzo dell'SMS in base al suo stato attuale)ridurre il saldo degli utenti in base al costo del messaggio inviato
registra la transazione nella raccolta delle transazioni
Ora qual è il problema con quello? MongoDB può eseguire aggiornamenti atomici su un solo documento. Nel flusso precedente potrebbe accadere che si verifichi un qualche tipo di errore e il messaggio venga archiviato nel database ma il saldo dell'utente non viene aggiornato e / o la transazione non viene registrata.
Ho avuto due idee:
Crea una singola raccolta per gli utenti e archivia il saldo come campo, transazioni e messaggi relativi all'utente come documenti secondari nel documento dell'utente. Poiché siamo in grado di aggiornare i documenti atomicamente, questo risolve effettivamente il problema di transazione. Svantaggi: se l'utente invia molti messaggi SMS, la dimensione del documento potrebbe aumentare e il limite del documento di 4 MB potrebbe essere raggiunto. Forse posso creare documenti storici in tali scenari, ma non penso che sarebbe una buona idea. Inoltre, non so quanto veloce sarebbe il sistema se invii sempre più dati allo stesso grande documento.
Crea una raccolta per gli utenti e una per le transazioni. Esistono due tipi di transazioni: acquisto di credito con cambio saldo positivo e messaggi inviati con cambio saldo negativo. La transazione può avere un documento secondario; ad esempio nei messaggi inviati i dettagli dell'SMS possono essere incorporati nella transazione. Svantaggi: non memorizzo il saldo utente corrente, quindi devo calcolarlo ogni volta che un utente tenta di inviare un messaggio per dire se il messaggio potrebbe passare o meno. Temo che questo calcolo possa rallentare con l'aumentare del numero di transazioni archiviate.
Sono un po 'confuso su quale metodo scegliere. Ci sono altre soluzioni? Non sono riuscito a trovare online le migliori pratiche su come aggirare questo tipo di problemi. Immagino che molti programmatori che stanno cercando di acquisire familiarità con il mondo NoSQL affrontino problemi simili all'inizio.