Wiem, że są tutaj podobne pytania, ale albo mówią mi, żebym przełączył się z powrotem na zwykłe systemy RDBMS, jeśli potrzebuję transakcji, albo użyj operacji atomowych lub zatwierdzania dwufazowego . Drugie rozwiązanie wydaje się najlepszym wyborem. Trzeci, za którym nie chcę podążać, ponieważ wydaje się, że wiele rzeczy może pójść nie tak i nie mogę tego przetestować pod każdym względem. Mam trudności z refaktoryzacją mojego projektu, aby wykonać operacje atomowe. Nie wiem, czy wynika to z mojego ograniczonego punktu widzenia (do tej pory pracowałem tylko z bazami danych SQL), czy też faktycznie nie można tego zrobić.
Chcielibyśmy przeprowadzić pilotażowe testy MongoDB w naszej firmie. Wybraliśmy stosunkowo prosty projekt - bramkę SMS. Pozwala naszemu oprogramowaniu na wysyłanie wiadomości SMS do sieci komórkowej, a bramka wykonuje brudną robotę: faktycznie komunikuje się z dostawcami za pośrednictwem różnych protokołów komunikacyjnych. Brama zarządza również fakturowaniem wiadomości. Każdy klient zgłaszający się do usługi musi wykupić kilka kredytów. System automatycznie zmniejsza saldo użytkownika w przypadku wysłania wiadomości i odmawia dostępu, jeśli saldo jest niewystarczające. Ponieważ jesteśmy klientami zewnętrznych dostawców usług SMS, możemy również mieć u nich własne salda. Te również musimy śledzić.
Zacząłem się zastanawiać, jak mogę przechowywać wymagane dane w MongoDB, jeśli zredukuję trochę złożoności (rozliczenia zewnętrzne, wysyłanie SMS-ów w kolejce). Pochodząc ze świata SQL, stworzyłbym osobną tabelę dla użytkowników, drugą dla wiadomości SMS i jedną do przechowywania transakcji dotyczących salda użytkowników. Powiedzmy, że tworzę osobne kolekcje dla wszystkich w MongoDB.
Wyobraź sobie zadanie wysyłania wiadomości SMS z następującymi krokami w tym uproszczonym systemie:
sprawdzić, czy użytkownik ma wystarczającą równowagę; odmów dostępu, jeśli nie ma wystarczających środków
wysłać i zapisać wiadomość w kolekcji SMS ze szczegółami i kosztem (w systemie na żywo wiadomość miałaby
status
atrybut, a zadanie odebrałoby ją do doręczenia i ustalało cenę SMS-a zgodnie z jego aktualnym stanem)zmniejszyć saldo użytkowników o koszt wysłanej wiadomości
zarejestruj transakcję w kolekcji transakcji
Jaki jest z tym problem? MongoDB może wykonywać niepodzielne aktualizacje tylko w jednym dokumencie. W poprzednim przepływie może się zdarzyć, że wkradnie się jakiś błąd i wiadomość zostanie zapisana w bazie danych, ale saldo użytkownika nie jest aktualizowane i / lub transakcja nie jest rejestrowana.
Wpadłem na dwa pomysły:
Utwórz pojedynczą kolekcję dla użytkowników i przechowuj saldo jako pole, transakcje związane z użytkownikiem i komunikaty jako dokumenty podrzędne w dokumencie użytkownika. Ponieważ możemy aktualizować dokumenty w sposób atomowy, w rzeczywistości rozwiązuje to problem transakcji. Wady: jeśli użytkownik wyśle wiele wiadomości SMS, rozmiar dokumentu może stać się duży i może zostać osiągnięty limit 4 MB dokumentów. Może uda mi się stworzyć dokumenty historyczne w takich scenariuszach, ale nie sądzę, żeby to był dobry pomysł. Nie wiem też, jak szybki byłby system, gdybym wypychał coraz więcej danych do tego samego dużego dokumentu.
Utwórz jedną kolekcję dla użytkowników i jedną dla transakcji. Mogą być dwa rodzaje transakcji: zakup kredytowy z dodatnią zmianą salda oraz wiadomości wysłane z ujemną zmianą salda. Transakcja może mieć dokument podrzędny; na przykład w wysyłanych wiadomościach szczegóły SMS-a mogą być osadzone w transakcji. Wady: nie przechowuję aktualnego salda użytkownika, więc muszę je obliczać za każdym razem, gdy użytkownik próbuje wysłać wiadomość, aby stwierdzić, czy wiadomość może przejść, czy nie. Obawiam się, że te obliczenia mogą stać się powolne w miarę wzrostu liczby przechowywanych transakcji.
Jestem trochę zdezorientowany, którą metodę wybrać. Czy są inne rozwiązania? Nie udało mi się znaleźć w internecie żadnych sprawdzonych metod dotyczących rozwiązywania tego typu problemów. Myślę, że wielu programistów, którzy próbują zaznajomić się ze światem NoSQL, ma na początku podobne problemy.