GN⁺: 데이터베이스 없이 고가용성 웹 서비스 구축
(blog.screenshotbot.io)데이터베이스 없이 고가용성 웹 서비스 구축하기
탐색
- 새로운 스타트업의 경우, 보통 Rails, Django, Node와 같은 웹 프레임워크와 MySQL, PostgreSQL, MongoDB와 같은 데이터베이스를 선택함
- 하지만 웹 서비스와 데이터베이스 인스턴스를 하나로 합칠 수 있다면? 모든 데이터를 RAM에 저장하는 방식으로 접근 가능
- RAM을 데이터베이스로 사용하면 SQL 쿼리로 데이터를 직렬화할 필요가 없어짐
- 인덱스는 메모리 내 해시 테이블을 사용하여 구현 가능
- 백그라운드 작업은 큰 프로세스 내의 스레드로 처리 가능
- 프로세스가 충돌할 경우, 주기적으로 RAM의 스냅샷을 찍고 변경 사항을 디스크에 기록하여 복구 가능
확장
- 고가용성을 요구하는 고객이 생기면, Raft 합의 알고리즘을 사용하여 서버를 복제함
- 리더 서버가 다운되면 새로운 리더가 선출되어 요청을 처리함
- 이 방식으로 서버를 재시작하지 않고도 롤링 배포 가능
추출
- 큰 고객이 많아지면 샤딩을 통해 웹 서비스를 분할하여 처리 가능
- 각 엔터프라이즈 고객에게 전용 클러스터를 제공함
- 주요 병목 현상은 커밋 스레드의 성능이 될 수 있음
우리의 스택
- Common Lisp 사용: 다중 스레드 지원이 뛰어나고, 코드 핫 리로딩에 적합함
- bknr.datastore와 bknr.cluster 사용: Raft 구현을 위해 Baidu의 Braft 라이브러리 사용
- 이미지 파일 저장을 위해 EFS 사용: S3보다 오류 처리와 테스트가 용이함
요약
- 이 아키텍처는 새로운 스타트업에 적합하며, Common Lisp을 사용하면 많은 도구가 이미 준비되어 있음
- bknr.datastore, Braft, Raft의 기여에 감사함
GN⁺의 정리
- 이 글은 데이터베이스 없이 고가용성 웹 서비스를 구축하는 새로운 아키텍처를 소개함
- RAM을 데이터베이스로 사용하고, Raft 합의 알고리즘을 통해 고가용성을 보장함
- Common Lisp을 사용하여 다중 스레드와 코드 핫 리로딩을 지원함
- 이 아키텍처는 새로운 스타트업에 적합하며, 빠른 개발과 디버깅이 가능함
- 유사한 기능을 가진 프로젝트로는 Redis와 Memcached가 있음
Hacker News 의견
-
SQLite를 사용하지 않고 자체 트랜잭션 로그를 만드는 것은 이상함
- 데이터가 한 서버에 맞으면 그냥 그 서버에서 데이터베이스를 실행하는 것이 좋음
- 데이터가 RAM에 맞으면 ramdisk를 사용하고 표준 도구로 영구 저장소에 복제하는 것이 간단함
-
MySQL, Postgres, Redis, MongoDB 등을 사용하지 않고 자체 메모리 내 데이터베이스를 만드는 것은 복잡함
- 트랜잭션을 직렬화하고 디스크에 기록해야 함
- 웹 서버 간의 트랜잭션 로그를 동기화하고 메모리 내 데이터베이스를 업데이트해야 함
- 충돌 해결 알고리즘을 작성해야 함
- 웹 서버를 테넌트별로 샤딩하고 로드 밸런싱 계층을 작성해야 함
-
MySQL이나 Postgres의 기본적인 측면을 배우지 않으려는 것은 시간 낭비임
- 공용 클라우드 제공자에서 실행할 때 기본 튜닝으로 동시성 문제를 해결할 수 있음
- 1천만 행을 추가하는 것은 큰 문제가 아님
- 더 나쁜 상황이 올 때까지 기다렸다가 해결하는 것이 더 현명함
-
HashiCorp의 Nomad, Consul, Vault와 유사한 아키텍처임
- 개발자 경험이 좋음
- 메모리 내 상태를 원하는 대로 설정할 수 있음
- 새로운 스타트업에는 적합하지 않음
- 업그레이드가 특히 어려움
-
RAM이 매우 저렴하다는 오해가 있음
- SSD와 vCPU 성능은 크게 향상되었지만 RAM 가격은 크게 떨어지지 않음
- DRAM 가격은 주기적으로 변동하며, 최근에야 약간 저렴해짐
-
파일 시스템 디렉토리를 테이블로, JSON 파일을 행으로 사용하는 프로젝트를 본 적이 있음
- Redis, Mongo, Postgres를 고려했지만 자체 데이터베이스를 구축함
- 혁신적인 토큰을 데이터베이스 구축에 사용하는 것은 비효율적임
-
관계형 데이터베이스를 사용하는 것이 더 안정적임
- 내장된 중복성, 트랜잭션 로그, 백업, 복구 기능이 있음
- 대부분의 경우 데이터베이스를 사용하는 것이 좋음
-
복잡한 것을 피하기 위해 자체 Raft 합의 계층을 구현함
- Redis를 사용하는 것이 더 간단할 수 있음
-
현대의 데스크탑 및 모바일 앱은 종종 SQLite와 같은 데이터베이스를 사용함
- 관계형 데이터 저장 및 쿼리가 유용함
-
자체 메모리 내 데이터베이스를 구축하는 것이 Postgres나 SQLite를 설치하는 것보다 간단하지 않음
- 동시성 코드를 작성하는 것보다 SQL을 작성하는 것이 더 쉬움