Я знаю, что здесь есть похожие вопросы, но они либо говорят мне , чтобы переключиться обратно на обычные системы СУБД, если мне нужны транзакции, либо используют атомарные операции или двухфазные совершить . Второе решение кажется лучшим выбором. Третий, которому я не хочу следовать, потому что кажется, что многие вещи могут пойти не так, и я не могу проверить это во всех аспектах. Мне трудно рефакторинг моего проекта для выполнения атомарных операций. Я не знаю, исходит ли это от моей ограниченной точки зрения (я до сих пор работал только с базами данных SQL), или это на самом деле невозможно.
Мы бы хотели провести пилотное тестирование MongoDB в нашей компании. Мы выбрали относительно простой проект - SMS-шлюз. Это позволяет нашему программному обеспечению отправлять SMS-сообщения в сотовую сеть, и шлюз выполняет грязную работу: фактически общаясь с поставщиками через различные протоколы связи. Шлюз также управляет выставлением счетов за сообщения. Каждый клиент, который подает заявку на услугу, должен купить несколько кредитов. Система автоматически уменьшает баланс пользователя при отправке сообщения и запрещает доступ, если баланс недостаточен. Кроме того, поскольку мы являемся клиентами сторонних поставщиков SMS-сообщений, у нас также может быть свой баланс. Мы также должны следить за ними.
Я начал думать о том, как сохранить необходимые данные с MongoDB, если урезать некоторые сложности (внешний биллинг, отправка SMS в очереди). Исходя из мира SQL, я бы создал отдельную таблицу для пользователей, другую для SMS-сообщений и одну для хранения транзакций, касающихся баланса пользователей. Допустим, я создаю отдельные коллекции для всех в MongoDB.
Представьте себе задачу отправки SMS со следующими шагами в этой упрощенной системе:
проверить, имеет ли пользователь достаточный баланс; запретить доступ, если недостаточно средств
отправьте и сохраните сообщение в коллекции SMS с подробностями и стоимостью (в действующей системе сообщение будет иметь атрибут status
, и задание получит его для доставки и установит цену SMS в соответствии с текущим состоянием)
уменьшить баланс пользователей на стоимость отправленного сообщения
регистрация транзакции в коллекции транзакций
Теперь, в чем проблема? MongoDB может делать атомарные обновления только для одного документа. В предыдущем потоке могло случиться, что появляется какая-то ошибка, и сообщение сохраняется в базе данных, но баланс пользователя не обновляется и / или транзакция не регистрируется.
Я пришел с двумя идеями:
Создайте единую коллекцию для пользователей и сохраните баланс в виде поля, связанные с пользователем транзакции и сообщения в качестве вложенных документов в документе пользователя. Поскольку мы можем обновлять документы атомарно, это фактически решает проблему транзакции. Недостатки: если пользователь отправляет много SMS-сообщений, размер документа может увеличиться и может быть достигнут лимит в 4 МБ. Может быть, я могу создавать исторические документы в таких сценариях, но я не думаю, что это было бы хорошей идеей. Кроме того, я не знаю, как быстро будет работать система, если я добавлю все больше и больше данных в один и тот же большой документ.
Создайте одну коллекцию для пользователей и одну для транзакций. Может быть два вида транзакций: покупка в кредит с положительным изменением баланса и отправка сообщений с отрицательным изменением баланса. Транзакция может иметь поддокумент; например, в отправленных сообщениях детали SMS могут быть встроены в транзакцию. Недостатки: я не сохраняю текущий баланс пользователя, поэтому мне приходится рассчитывать его каждый раз, когда пользователь пытается отправить сообщение, чтобы узнать, может ли сообщение пройти или нет. Боюсь, что этот расчет может стать медленным по мере роста количества хранимых транзакций.
Я немного запутался в том, какой метод выбрать. Есть ли другие решения? Я не мог найти лучшие практики онлайн о том, как обойти подобные проблемы. Я предполагаю, что многие программисты, которые пытаются познакомиться с миром NoSQL, сталкиваются с подобными проблемами в начале.