티스토리 뷰
Relational DB
ACID
ACID란 원자성, 일관성, 고립성, 지속성의 약자로 DB 트랜잭션이 안전하게 수행됨을 보장한다.
트랜잭션(Transaction) : DB의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 일련의 연산
1. Actomicity (원자성)
- 각 트랜잭션이 완전히 성공하거나 완전히 실패함을 보장한다. 이는 DB의 부분 업데이트를 방지한다.
- 입금 프로세스를 예로들자면 A가 B에게 입금을 하는데 A에서 돈이 빠져나오는 action, B에 돈을 입금하는 action이 모두 이루어 져야 원자성을 지킬 수 있으며, A에서 돈을 빼고 B에 입금이 되지 않는다면 그대로 돈이 유실되어버린다.
2. Consistency (일관성)
- 트랜잭션의 수행 전/후의 DB는 항상 일관된 상태여야 한다.
- mainDB A와 replica인 B가 있다고 할 때, A라는 DB에 데이터가 쌓였다면, B에도 동일한 데이터가 쌓여야 한다.
3. Isolation (고립성)
- 트랜잭션 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장한다.
- A, B, C, D 트랜젝션이 있는데 각 트렌젝션의 작업은 서로 영향을 주면 안된다.
- 은행 관리자는 이체 작업이 진행되는 도중에 Query를 실행하더라도 이체 작업을 볼 수 없고, 실행시킨 Query는 이체 작업이 종료 된 이후에 실행된다.
4. Durability (지속성)
- 성공적으로 수행된 트랜잭션은 영원히 반영되어야 한다.
- RAM 메모리마냥 휘발성이 되면 안된다.
NoSQL
Document DB
- 테이블의 스키마가 유동적이며, 각 레코드 마다 다른 스키마를 가질 수 있다.
- JSON과 같은 Document를 이용하여 레코드를 저장할 수 있다. (하나의 Giant Object)
- Key value pair 형태로 저장할 수 있다.
- ex) Mongo DB
{
'name': 'user1',
'address': {
'localCode': '02',
'country': 'Kr'
}
}
{
'name': 'user2',
'age': 1,
'address': {
'localCode': '032',
'country': 'Kr'
}
}
id | name | age |
1 | user1 | null |
2 | user2 | 1 |
위와 같이 컬럼에 해당하는 데이터가 없으면 저장이 되지 않는 SQL과 다르게 1번의 age가 없어도 저장이 된다.
- 장점
- 값이 없더라도 무조건 공간이 필요하던 RDB와는 달리, 저장하지 않을 수 있으므로 공간을 덜차지한다.
- 여러개의 테이블을 하나의 Document에 모아둘 수 있으므로, 조회 시 한 번의 조회로 필요한 데이터를 획득할 수 있다. (join 대체) 그래서 데이터 접근 속도가 빠르다.
Blob Storage DB
- 비디오, 이미지, 대량의 text 바이너리 데이터 형식을 Blob 데이터 타입이라고 한다.
- ex) S3, GCS(Google Cloud Storage), Azur Blob Storage
Time series DB (시계열 DB)
- 하나 이상의 시간과 하나 이상의 value pair를 통해 시계열(일정 산격으로 배치된 데이터의 수열)을 저장하고 서비스하는데 최정화 된 소프트웨어 시스템이다.
- log 데이터를 쌓을 때 많이 사용한다.
- purchase order, employee activity등 대량의 데이터를 저장하는 Amazon과 같은 대형 기업에서 사용할 수 있다.
- ex) influxDB, prometheusDB
GDB (Graph DB)
- 데이터를 그래프(node, edge)로 저장하고 표현하는 DB이다.
- GDB는 edge를 통해 데이터에 해당하는 node간 관계를 직접 정할 수 있으며, 데이터의 관계를 그래프를 통해 직관적으로 시각화 할 수 있다.
- 데이터 간 관계를 표현할 필요가 있을경우 사용할 수 있다. (사람간 관계를 표현할 SNS 서비스 등)
- 한 User와 팔로우를 맺은 User List를 조회한다고 할 때 DB에 저장된 모든 회원을 순회하여 검색해야 되므로 어마어마하게 느리다.
- 이러한 불합리적인 구조는 Graph DB를 사용하여 개선할 수 있다.
- 한 User에 대한 관계도는 edge로 연결되므로 관계없는 User는 순회하지 않는다. (관련 없는 Node는 고려하지 않음)
- ex) netflix, google, naver 등에서 사용한다.
naver d2 : https://d2.naver.com/helloworld/8446520
neo4j 예제
Cypher Query를 사용한 Graph Query 서비스를 지원한다.
create(samsung:Company {name: 'Samsung'})
create(SK:Comapny {name: 'SK'})
create(LG:Company {name: 'LG'})
create(employer:employee {name: 'employer'})
create(employee1:employee {name: 'employee1'})
create(employee2:employee {name: 'employee2'})
create(employee3:employee {name: 'employee3'})
create(employee4:employee {name: 'employee4'})
create(employer)-[:WORKFOR {role: 'employer'}] -> (samsung)
create(employee1)-[:WORKFOR {role: 'employer'}] -> (samsung)
create(employee2)-[:WORKFOR {role: 'employer'}] -> (samsung)
create(employee3)-[:STUDYAT] ->(SK)
create(employee4)-[:STUDYAT] ->(SK)
create(employee1)-[:STUDYAT] ->(LG)
create(employee2)-[:STUDYAT] ->(LG)
create(employee3)-[:STUDYAT] ->(LG)
create(employee4)-[:STUDYAT] ->(LG)
SpatialDB
- 공간 데이터를 다루기 위해 특수한 목적으로 사용되는 DB
- 좌표로 표현할 수 있는 공간 객체들을 데이터화 해서 보다 쉽게 저장
- 저장한 공간 데이터에 대해 다양하고 손쉬운 연산을 수행
- ex) QuadTree DB
DB 전략
Replication
- 목적
- single point of failure
- read/write 노드를 분리하여 성능 분산을 처한다.
- backup
- main db에 장애가 생기더라도 copy db에서 정상적인 서비스를 빠르게 구성하도록 한다.
- 주의할 점
- Replication을 할때 데이터 일관성(consistency)가 매우 중요하다.
- 비동기적으로 데이터를 업데이트해야될 경우가 있다.
- main db의 내용을 replica(Slave DB)로 replication하는 과정에는 동기/비동기 방식이 있고, 비동기 방식으로 업데이트 할 경우 데이터 일관성이 깨질 수 있다.
- 블로그 서비스와 같이 변경 사항이 바로 업데이트 되지 않아도 괜찮을 경우 비동기 방식을 사용할 수 있다.
Sharding
- 단일 논리적 데이터셋을 다수 DB에 나누어 저장하는 방법이다.
- 데이터를 분산 저장함으로써, 트래픽을 분산시킨다.
- 방식
- Vertical Sharding
- Horizontal Sharding
- 대부분 Horizontal Sharding 방식을 사용한다.
- first name의 사전 순서대로 자를 때, 문자열을 A-K, L-S, T-Z로 각각 나눈다.
- request throughput을 줄이기 위해 나누었지만, A-K보다 T-Z쪽의 데이터가 훨씬 적을 경우 현명한 sharing을 했다고 볼 수 없다.
- 요청을 최대한 고르게 나누기 위해 Hashing알고리즘을 사용할 수 있다.
Hashing 알고리즘을 이용하여 Reverse Proxy(로드밸런서) 구현 후 실행
- user 데이터를 userDB에 저장할 때, name 문자열의 각 문자를 ASCII 값으로 바꾼 후, 모두 더하고, 서버수 (SHARD_COUNT)로 나눈 나머지 값을 shardIdx로 둔다.
- 각 서버에 저장되어 있는 list(SHARD_ADDRESSES)에서 shardIdx를 키값으로 서버를 선택한다.
- 해당 서버에 값을 저장한다.
- 단순하게 나누었을때 보다 고르게 저장이 된다.
'시스템 디자인' 카테고리의 다른 글
시스템 디자인 7주차 (0) | 2021.08.30 |
---|---|
시스템 디자인 6주차 (0) | 2021.08.26 |
시스템 디자인 4주차 (0) | 2021.07.31 |
시스템 디자인 3주차 (0) | 2021.07.21 |
시스템 디자인 2주차 (0) | 2021.07.18 |