나는 여기에 비슷한 질문이 있다는 것을 알고 있지만 트랜잭션이 필요하거나 원자 연산 또는 2 단계 커밋을 사용하는 경우 일반 RDBMS 시스템으로 다시 전환 하라고 지시합니다 . 두 번째 솔루션이 최선의 선택 인 것 같습니다. 세 번째는 많은 일이 잘못 될 수 있고 모든 측면에서 테스트 할 수 없기 때문에 따르고 싶지 않습니다. 원자 작업을 수행하기 위해 프로젝트를 리팩토링하는 데 어려움을 겪고 있습니다. 나는 이것이 제한된 관점에서 왔는지 (지금까지는 SQL 데이터베이스로만 작업 했음) 또는 실제로 수행 할 수 있는지 여부를 알 수 없습니다.
우리 회사에서 MongoDB를 시범 테스트하고 싶습니다. 우리는 SMS 게이트웨이라는 비교적 간단한 프로젝트를 선택했습니다. 그것은 우리의 소프트웨어가 셀룰러 네트워크에 SMS 메시지를 보낼 수있게하며 게이트웨이는 더러운 작업을 수행합니다. 실제로 다른 통신 프로토콜을 통해 공급자와 통신합니다. 게이트웨이는 또한 메시지 청구를 관리합니다. 서비스를 신청하는 모든 고객은 약간의 크레딧을 구매해야합니다. 메시지가 전송 될 때 시스템은 자동으로 사용자의 잔액을 줄이고 잔액이 부족하면 액세스를 거부합니다. 또한 우리는 타사 SMS 제공 업체의 고객이므로 그들과 자체 균형이있을 수도 있습니다. 우리도 그것들을 추적해야합니다.
복잡성 (외부 청구, 대기중인 SMS 전송)을 줄이면 MongoDB에 필요한 데이터를 저장하는 방법에 대해 생각하기 시작했습니다. SQL 세계에서 온 사용자를 위해 별도의 테이블을 만들고, 다른 하나는 SMS 메시지를 위해, 다른 하나는 사용자 균형에 관한 트랜잭션을 저장하기위한 테이블을 만듭니다. MongoDB의 모든 콜렉션에 대해 별도의 콜렉션을 작성한다고 가정 해 봅시다.
이 단순화 된 시스템에서 다음 단계로 SMS 전송 작업을 상상해보십시오.
사용자에게 잔액이 충분한 지 확인하십시오. 크레딧이 충분하지 않으면 액세스 거부
세부 정보 및 비용과 함께 SMS 컬렉션에 메시지를 보내고 저장합니다 (라이브 시스템에서는 메시지에
status
특성이 있고 작업이 배달을 위해 메시지를 받아 현재 상태에 따라 SMS 가격을 설정 함).보낸 메시지 비용으로 사용자 잔액을 줄입니다.
트랜잭션 콜렉션에 트랜잭션을 기록하십시오.
이제 문제가 무엇입니까? MongoDB는 하나의 문서에서만 원자 업데이트를 수행 할 수 있습니다. 이전 흐름에서는 일종의 오류가 발생하여 메시지가 데이터베이스에 저장되지만 사용자 잔액이 업데이트되지 않거나 트랜잭션이 기록되지 않을 수 있습니다.
나는 두 가지 아이디어를 생각해 냈습니다.
사용자에 대한 단일 콜렉션을 작성하고 잔액을 필드, 사용자 관련 트랜잭션 및 메시지를 사용자 문서의 하위 문서로 저장하십시오. 문서를 원자 적으로 업데이트 할 수 있기 때문에 실제로 트랜잭션 문제가 해결됩니다. 단점 : 사용자가 많은 SMS 메시지를 보내면 문서 크기가 커지고 4MB 문서 제한에 도달 할 수 있습니다. 그런 시나리오에서 기록 문서를 만들 수는 있지만 이것이 좋은 생각은 아닙니다. 또한 더 큰 데이터를 동일한 큰 문서로 푸시하면 시스템이 얼마나 빠른지 알 수 없습니다.
사용자를위한 하나의 컬렉션과 트랜잭션을위한 하나의 컬렉션을 만듭니다. 거래 는 긍정적 인 잔액 변경으로 신용 구매 와 부정적인 잔액 변경으로 전송 된 메시지 의 두 가지 종류가 있습니다. 트랜잭션에는 하위 문서가있을 수 있습니다. 예를 들어, 전송 된 메시지 에서 SMS의 세부 사항은 트랜잭션에 임베드 될 수 있습니다. 단점 : 현재 사용자 잔액을 저장하지 않으므로 사용자가 메시지를 보낼 때마다 메시지를 보낼 때마다 계산해야합니다. 저장된 트랜잭션 수가 증가함에 따라이 계산이 느려질 수 있습니다.
어떤 방법을 선택 해야할지 조금 혼란 스럽습니다. 다른 해결책이 있습니까? 이러한 종류의 문제를 해결하는 방법에 대한 온라인 모범 사례를 찾을 수 없었습니다. NoSQL 세계에 익숙해 지려는 많은 프로그래머들이 처음에 비슷한 문제에 직면하고 있다고 생각합니다.