MongoDB

MongoDB 정리

ZzangHo 2022. 2. 15. 14:48
728x90

NoSQL이란?

공식 홈페이지에 보면 NoSQL은 "non SQL" 또는 "Not Only SQL"의 약자로 많이 생각하며 대부분의 사람들은 NoSQL 데이터베이스가 관계형 데이터베이스 이외의 형식으로 데이터를 저장하는 데이터베이스라는 데 동의한다고 한다.
우리가 흔히 쓰는 RDBMS으로는 MySQL, Oracle, MS-SQL 등이 있고 NoSQL로는 MongoDB, Redis 등이 있다고 한다.

 

RDBMS vs NoSQL

  RDBMS NoSQL
적합한 사용사례 데이터 정합성이 보장되어야 하는 은행 시스템 낮은 지연 시간, 가용성이 중요한 SNS 시스템
데이터 모델 정규화와 참조 무결성이 보장된 스키마 스키마가 없는 자유로운 데이터 모델
트랜잭션 강력한 ACID 지원 완화된 ACID(BASE)
확장 하드웨어 강화(Scale up) 수평 확장 가능한 분산 아키텍처(Scale out)
API SQL 쿼리 객체 기반 API 제공

위와 같이 각각의 성격들이 있지만 점점 서로의 장점을 흡수하고 있다고 한다. 장점들을 흡수하여 기능을 제공하고 있지만 주무기가 아니기 때문에 참고용으로만 알면 좋을것 같다.

 

 

아래는 내가 생각한 MongoDB의 장,단점을 적어 보겠다.

MongoDB의 장점

  • Schema less
  • RDBMS 보다 굉장히 빠르다(100배 이상 빠르다고 한다.)
  • scale out 구조로 대용량 데이터 적재 가능

 

MongoDB의 단점

  • 복잡한 쿼리를 사용할 수 없다.(Join 기능을 지원 하지만 성능 최악)
  • 메모리 사용량이 크다
  • 기존에 RDBMS를 사용하던 유저들에게는 쿼리 진입벽이 좀 높다. 

 

MongoDB의 특징

  • Document
  • BASE
  • Open Source

이렇게 세 가지의 특징을 가지고 있다고 한다.

 

Document

MongoDB는 Document 기반 데이터베이스이다.
Database > Collection -> Document -> Field 계층으로 이루어져 있으며 아래 그림을 통해 RDBMS와 비교해 보자

 

RDBMS와 MongoDB 비교

 

Document 형태 데이터베이스의 경우 스키마의 의존적인 RDBMS와 다르게 자유롭게 스키마를 동적으로 추가 할 수 있다. 이번에 팀에서 데이터 파이프라인 표준화를 위해 MongoDB를 사용한 이유도 바로 이 점 때문이였다. 

쇼핑, 도서, 투어, 티켓 이 4개의 도메인의 데이터를 카프카에서 모두 가져올 때 RDBMS의 경우 필드 하나만 추가되어도 우리쪽에서 작업해야 하는 포인트 들이 너무 많았기 때문이다. 대표적으로는 필드 추가, 컨슈머 소스 변경이 있겠지만 이런 작업들이 도메인이 여러개다 보니 작업이 많을 것으로 생각 하였다.

그래서 MongoDB를 이용하여 동적으로 추가 되는 필드에 대해서는 따로 작업을 해주지 않아도 자동으로 MongoDB에 추가가 되도록 아래처럼 데이터 모델링을 하였다.

 

## domain A Collection
{
    "_id" : ObjectId("000000000000000000000001"),
    "isdel" : "N",
    "meta" : {
        "a_field_1" : "value1",
        "a_field_2" : "value2",
        "a_field_3" : NumberLong(0),
        "a_field_4" : "00001",
        "a_field_5" : "Y",
        "a_field_6" : {
        	"a_sub_field_1" : "value1",
            "a_sub_field_2" : "value2"
        },
        "a_field_7" : ["a", "b", "c", "d"]
    },
    "offset" : NumberLong(3203786),
    "partition" : 1,
    "pk" : "00001",
    "shard_no" : 853
}

## domain B Collection
{
    "_id" : ObjectId("000000000000000000000001"),
    "isdel" : "N",
    "meta" : {
        "b_field_1" : NumberLong(1),
        "b_field_2" : ["a", "b", "c", "d"],
        "b_field_3" : NumberLong(0),
        "b_field_4" : "00001",
        "b_field_5" : "Y"
    },
    "offset" : NumberLong(3203786),
    "partition" : 1,
    "pk" : "00001",
    "shard_no" : 853
}

 

위 처럼 공통 필드들을 만들었고 meta 필드에 nested구조로 각각의 도메인의 데이터가 들어있도록 모든 도메인의 데이터를 신규 프로젝트에서는 공통 포맷으로 변경하였다. 이렇게 공통 포맷으로 만든 이후에 엇게 된 이점은 컨슈머 소스를 각 도메인마다 만들 필요가 없어 컨슈머 쪽 관리 포인트도 같이 줄어 들게 되었다. 컨슈머는 소스 1개로 여러 도메인의 데이터를 토픽명, 그룹명만 다르게 하여 띄우면 되었다. 

 

위의 샘플에서 보면 ObjectId가 기본에 보던 형태랑 다르다. 그 이유는 카프카로 동일한 데이터가 넘어 왔을 때 Update를 하기위해 ObjectId를 넘어오는 데이터에서 만들어서 따로 넣어주고 있다. 

그렇다면 기본 ObjectId의 형태는 어떻게 될까?

 

https://developer.mongodb.com/quickstart/bson-data-types-objectid

 

ObjectId는 RDBMS의 Primary Key와 같이 고유한 키 값으로 기본적으로 데이터를 저장하면 자동으로 생긴다. 이 역할을 클라이언트에서 해준다고 한다. 이는 MongoDB 클러스터에서 Sharding된 데이터를 빠르게 가져오기 위함인데 Router(mongos)에서 ObjectId를 보고 데이터가 존재하는 Shard에서 데이터를 요청할 수 있다고 한다. 

 

ObjectId는 세 영역으로 나뉘어져 있다. 각각 첫 4 byte는 UNIX Timestamp 정보를 담고 있고 다음 5 byte는 랜덤한 값 인데 그 안에서 또 3 byte와 2 byte로 나뉘어진다. 첫 3byte는 클라이언트의 머신별 고유한 키(mac address 또는 ip)를 이용하여 만들고 다음 2 byte는 process id를 이용한다고 한다. 5 byte를 채운 뒤 마지막 3 byte는 Auto Inrement 값으로 구성 된다.

 

위의 조건이 다 일치하지 않는 이상은 충돌이 일어나지 않는다고 한다.

 

BASE

BASE는 ACID와 대립되는 개념으로 다음 세 가지로 이루어져있다.
  • Basically Avaliable(기본적으로 사용 가능)
    • 기본적으로 언제든지 사용할 수 있다는 의미를 가지고 있다.
    • 즉, 가용성이 필요하다는 뜻을 가진다.
  • Soft state(부드러운 상태)
    • 외부의 개입이 없어도 정보가 변경될 수 있다는 의미를 가지고 있다.
    • 네트워크 파티션 등 문제가 발생되어 일관성(Consistency)이 유지되지 않는 경우 일관성을 위해 데이터를 자동으로 수정한다.
  • Eventually consistent(결국 일관성)
    • 일시적으로 일관적이지 않은 상태가 되어도 일정 시간 후 일관적인 상태가 되어야한다는 의미를 가지고 있다.
    • 장애 발생시 일관성을 유지하기 위한 이벤트를 발생시킨다.

이처럼 BASE는 ACID와는 다르게 일관성을 어느정도 포기하고 가용성을 우선시한다. 즉, 데이터가 조금 맞지 않더라도 일단 내려준다는 뜻이다.

 

 

MongoDB Replica Set

MongoDB는 클러스터를 구성하기 위해 가장 간단한 방법으로 Replica Set을 이용할 수 있다. 
Replica Set은 다음 두 방법을 이용하여 구성할 수 있다.
  • P-S-S
  • P-S-A

P-S-S

https://docs.mongodb.com/manual/replication/

P-S-S 구성은 하나의 Primary와 여러 개의 Secondary로 구성된 Replica Set이다.

요청은 Primary로 받고 Primary가 각 Secondary로 Replication을 해준다.

 

https://docs.mongodb.com/manual/replication/

만약 Primary가 죽을 경우 투표를 통해 남은 Secondary 중 새로운 Primary를 선출한다. 만약 Secondary가 1개 남은 경우 새로운 Primary를 선출 할 수 없기 때문에 서버 장애가 발생한다.(위험!)

 

P-S-A

https://docs.mongodb.com/manual/replication/

P-S-A 시스템은 하나의 Primary와 Arbiter 그리고 여러 개의 Secondary로 구성 된 Replica Set이다.

 

P-S-A 구성에서는 Primary가 죽는 경우 Arbiter가 Secondary와 함께 투표해서 Secondary 중 새로운 Primary를 선출한다. P-S-A 구성에선 Secondary가 하나만 남았더라도 Arbiter가 남아있으면 남은 Secondary를 Primary로 선출 할 수 있어 정상적인 서비스 운영이 가능하다. 

 

참고자료

https://docs.mongodb.com/manual/replication/

https://kciter.so/posts/about-mongodb