Sé que hay preguntas similares aquí, pero me están diciendo que vuelva a los sistemas RDBMS normales si necesito transacciones o uso operaciones atómicas o confirmación en dos fases . La segunda solución parece la mejor opción. El tercero no deseo seguirlo porque parece que muchas cosas podrían salir mal y no puedo probarlo en todos los aspectos. Me está costando refactorizar mi proyecto para realizar operaciones atómicas. No sé si esto proviene de mi punto de vista limitado (hasta ahora solo he trabajado con bases de datos SQL), o si realmente no se puede hacer.
Nos gustaría probar piloto MongoDB en nuestra empresa. Hemos elegido un proyecto relativamente simple: una puerta de enlace SMS. Permite que nuestro software envíe mensajes SMS a la red celular y la puerta de enlace hace el trabajo sucio: en realidad se comunica con los proveedores a través de diferentes protocolos de comunicación. El portal también gestiona la facturación de los mensajes. Cada cliente que solicita el servicio tiene que comprar algunos créditos. El sistema disminuye automáticamente el saldo del usuario cuando se envía un mensaje y niega el acceso si el saldo es insuficiente. Además, debido a que somos clientes de proveedores de SMS de terceros, también podemos tener nuestros propios saldos con ellos. Tenemos que hacer un seguimiento de esos también.
Empecé a pensar en cómo puedo almacenar los datos requeridos con MongoDB si reduzco cierta complejidad (facturación externa, envío de SMS en cola). Viniendo del mundo SQL, crearía una tabla separada para usuarios, otra para mensajes SMS y otra para almacenar las transacciones relacionadas con el saldo de los usuarios. Digamos que creo colecciones separadas para todos aquellos en MongoDB.
Imagine una tarea de envío de SMS con los siguientes pasos en este sistema simplificado:
verificar si el usuario tiene saldo suficiente; negar el acceso si no hay suficiente crédito
envíe y almacene el mensaje en la colección de SMS con los detalles y el costo (en el sistema en vivo el mensaje tendría un
status
atributo y una tarea lo recogería para la entrega y establecería el precio del SMS de acuerdo con su estado actual)disminuir el saldo de los usuarios por el costo del mensaje enviado
registrar la transacción en la colección de transacciones
¿Cuál es el problema con eso? MongoDB puede hacer actualizaciones atómicas solo en un documento. En el flujo anterior, podría ocurrir que algún tipo de error se deslice y el mensaje se almacene en la base de datos, pero el saldo del usuario no se actualiza y / o la transacción no se registra.
Se me ocurrieron dos ideas:
Cree una colección única para los usuarios y almacene el saldo como un campo, transacciones relacionadas con el usuario y mensajes como subdocumentos en el documento del usuario. Debido a que podemos actualizar los documentos atómicamente, esto realmente resuelve el problema de la transacción. Desventajas: si el usuario envía muchos mensajes SMS, el tamaño del documento podría aumentar y alcanzar el límite de 4 MB. Tal vez pueda crear documentos históricos en tales escenarios, pero no creo que sea una buena idea. Además, no sé qué tan rápido sería el sistema si inserto cada vez más datos en el mismo documento grande.
Cree una colección para usuarios y otra para transacciones. Puede haber dos tipos de transacciones: compra de crédito con cambio de saldo positivo y mensajes enviados con cambio de saldo negativo. La transacción puede tener un subdocumento; por ejemplo, en los mensajes enviados, los detalles del SMS se pueden incrustar en la transacción. Desventajas: no almaceno el saldo actual del usuario, así que tengo que calcularlo cada vez que un usuario intenta enviar un mensaje para saber si el mensaje podría pasar o no. Me temo que este cálculo puede volverse lento a medida que aumenta el número de transacciones almacenadas.
Estoy un poco confundido acerca de qué método elegir. ¿Hay otras soluciones? No pude encontrar ninguna de las mejores prácticas en línea sobre cómo solucionar este tipo de problemas. Supongo que muchos programadores que intentan familiarizarse con el mundo NoSQL se enfrentan a problemas similares al principio.