Я знаю, що тут є подібні запитання, але вони або кажуть мені перейти до звичайних систем RDBMS, якщо мені потрібні транзакції, або використовувати атомні операції або двофазну фіксацію . Друге рішення видається найкращим вибором. Третє, я не хочу слідувати, тому що, здається, багато речей можуть піти не так, і я не можу перевірити це в усіх аспектах. Мені важко переробити проект на виконання атомних операцій. Я не знаю, чи походить це з моєї обмеженої точки зору (я працював лише з базами даних SQL до цих пір), чи це насправді неможливо зробити.
Ми хотіли б провести тест MongoDB в нашій компанії. Ми обрали порівняно простий проект - SMS-шлюз. Це дозволяє нашому програмному забезпеченню відправляти SMS-повідомлення в стільникову мережу, а шлюз виконує брудну роботу: фактично спілкується з провайдерами за допомогою різних протоколів зв'язку. Шлюз також керує оплатою повідомлень. Кожен клієнт, який подає заявку на послугу, повинен придбати кілька кредитів. Система автоматично зменшує баланс користувача при надсиланні повідомлення та відмовляє у доступі, якщо баланс недостатній. Оскільки ми також є клієнтами сторонніх постачальників SMS, ми можемо також мати свої баланси з ними. Ми також повинні їх слідкувати.
Я почав замислюватися над тим, як я можу зберігати потрібні дані в MongoDB, якщо скорочую деяку складність (зовнішня виставлення рахунків, відправлення SMS у чергу). Виходячи зі світу SQL, я створив би окрему таблицю для користувачів, іншу для SMS-повідомлень та одну для зберігання транзакцій щодо балансу користувачів. Скажімо, я створюю окремі колекції для всіх тих, хто в MongoDB.
Уявіть завдання надсилання SMS із наступними кроками в цій спрощеній системі:
перевірити, чи є у користувача достатній баланс; заборонити доступ, якщо кредиту не вистачає
надіслати та зберігати повідомлення у колекції SMS із деталями та вартістю (у системі живого повідомлення повідомлення матиме
status
атрибут, а завдання підбере його для доставки та встановить ціну SMS відповідно до його поточного стану)зменшити залишок користувачів на вартість відправленого повідомлення
введіть транзакцію у збір транзакцій
Тепер у чому проблема? MongoDB може робити атомні оновлення лише на одному документі. У попередньому потоці може статися так, що якась помилка виповзає і повідомлення зберігається в базі даних, але баланс користувача не оновлюється та / або транзакція не реєструється.
Я придумав дві ідеї:
Створіть єдину колекцію для користувачів і зберігайте баланс як поле, пов’язані з користувачем транзакції та повідомлення як допоміжні документи в документі користувача. Оскільки ми можемо оновлювати документи атомним шляхом, це фактично вирішує проблему транзакцій. Недоліки: якщо користувач надсилає багато SMS-повідомлень, розмір документа може стати великим, а ліміт документа в 4 МБ може бути досягнутий. Можливо, я можу створювати документи з історії в таких сценаріях, але я не думаю, що це було б гарною ідеєю. Крім того, я не знаю, наскільки швидкою була б система, якщо я підсилюю все більше і більше даних до одного і того ж великого документа.
Створіть одну колекцію для користувачів та одну для транзакцій. Можливі два види транзакцій: покупка кредиту із зміною позитивного балансу та повідомлення, надіслане із зміною балансу. Транзакція може мати субдокумент; наприклад, у повідомленнях, що надсилаються, дані SMS можуть бути вбудовані в транзакцію. Недоліки: я не зберігаю поточний баланс користувача, тому мені доводиться обчислювати його кожен раз, коли користувач намагається надіслати повідомлення, щоб повідомити, чи може повідомлення пройти чи ні. Я боюся, що цей обчислення може стати повільним у міру зростання кількості збережених транзакцій.
Я трохи заплутався, який метод вибрати. Є інші рішення? В Інтернеті я не міг знайти жодної найкращої практики щодо вирішення подібних проблем. Я думаю, що багато програмістів, які намагаються ознайомитися зі світом NoSQL, на початку стикаються з подібними проблемами.