Database/MongoDB 2019. 9. 12. 18:22

 

요즘 시대에는 구글이나 페이스북과 같은 글로벌 서비스를 제공하는 회사가 늘어나면서 방대한 양의 데이터를 충분히 빠른 속도로 처리할 수 있는 데이터베이스에 대한 필요성이 대두되기 시작했다. 이런 대용량 데이터 서비스에서는 기존의 RDBMS에서 처리하기는 힘들다.(비용적인 문제, 데이터를 분산하기 위해 수십,수백대의 서버로 분산시켜야함) 물론 MySQL 같이 오픈 소스 RDBMS는 비용적인 문제를 해결해주기는 하였다. 하지만 이러한 MySQL도 빅데이터를 처리하기에는 문제가 있다. 만약 엄청난 양의 데이터가 있고, 매번 데이터베이스 스키마에 맞게 데이터를 조작하여 작업을 해야한다면 얼마나 비효율적이고 힘든 작업일까..

 

여느 NoSQL과 같이 MongoDB는 이러한 문제를 해결하기 위해 적합한? 데이터베이스이다. 솔루션 자체적으로 분산 처리, 샤딩, 데이터 리밸런싱, 데이터 복제, 복구 등을 지원하고 무엇보다 Schema-Free(Schema-less)한 구조이기에 대용량의 데이터 작업에 아주 효율적인 데이터베이스이다. 또한 일부 RDBMS의 기능을 제공하기도 한다.(인덱싱 등, 내부적으로 B-Tree 자료구조를 이용하여 인덱스를 관리.)

 

 

What Is MongoDB?

MongoDB is a document database with the scalability and flexibility that you want with the querying and indexing that you need.

www.mongodb.com

공식 홈페이지에 나와있는 MongoDB의 소개이다.

 

  • MongoDB 는 유연하고 JSON과 유사한 문서에 데이터를 저장합니다 . 즉, 필드는 문서마다 다를 수 있으며 시간에 따라 데이터 구조를 변경할 수 있습니다.

  • 문서 모델 은 응용 프로그램 코드의 객체에 매핑 되므로 데이터를 쉽게 사용할 수 있습니다.

  • 임시 쿼리, 인덱싱 및 실시간 집계 는 데이터에 액세스하고 분석하는 강력한 방법을 제공합니다

  • MongoDB는 기본적 으로 분산 데이터베이스 이므로 고 가용성, 수평 확장 및 지리적 분포가 내장되어 있고 사용하기 쉽습니다.

  • MongoDB는 무료로 사용할 수 있습니다 . 

 

그렇다면 MongoDB와 기존의 RDBMS와의 차이점은 무엇일까?

 

데이터를 저장하는 자료 구조 관점에서 보면 MongoDB와 RDBMS는 많은 공통점이 있다. MongoDB에서는 컬렉션(Collection)이나 도큐먼트(Document)와 같이 객체의 이름이 조금 다를 뿐 RDBMS와 비슷한 역할을 한다.

 

MongoDB RDBMS
데이터베이스(Database) 데이터베이스(Database)
컬렉션(Collection) 테이블(Table)
도큐먼트(Document) 레코드(Record OR Row)
필드(Field) 컬럼(Column)
인덱스(Index) 인덱스(Index)
쿼리의 결과로 "커서(Cursor)" 반환 쿼리의 결과로 "레코드(Record)" 반환

 

MongoDB는 쿼리의 결과로 커서를 반환하는데, 응용 프로그램이나 MongoDB 클라이언트 프로그램에서 커서를 통해 반복적으로 실제 도큐먼트를 가져올 수 있다. MongoDB에서 쿼리의 결과로 커서를 반환하는 이유는 쿼리의 결과를 클라이언트 서버의 메모리에 모두 담아두지 않아도 처리할 수 있게 하기 위해서다. 물론 MongoDB에서 커서를 읽을 때마다 서버(MongoDB 서버)에서 그때그때 도큐먼트를 가져오는 것은 아니고, 필요할 때마다 지정된 페이지 사이즈 단위로 서버로부터 전송받아 MongoDB 클라이언트 서버에 캐싱한 후에 유저에게 서비스하는 것이다.

 

많은 사람이 이야기하는 MongoDB의 특성으로는 다음과 같은 것들이 있다.

  • NoSQL
  • 스키마 프리(Schema-Free)
  • 비 관계형 데이터베이스

MongoDB는 RDBMS의 SQL을 사용하지는 않지만  MongoDB는 SQL 못지 않은 다양한 종류의 쿼리문을 지원한다.(필터링, 수집, 정렬, 정규 표현식 등) 또한 MongoDB는 외래키를 명시적으로 지원하지는 않지만, 논리적으로 도큐먼트 간의 관계(Embedded Document)를 만들어서 사용하는 데에는 아무런 문제가 없다. 그리고 RDBMS와 같지는 않지만 "$lookup"이라는 집계 기능을 이용하면 관계형데이터베이스와 비슷한 형태의 조인 처리를 수행할 수 있다.(샤딩 환경에서는 여러 제약이 존재)

 

스키마 프리가 아마도 MongoDB&RDBMS를 구분 지어줄 수 있는 가장 좋은 단어가 이다. 여기에서 스키마 프리는 테이블의 컬럼 수준에만 적용되는데, 사용할 컬럼을 미리 정의하지 않고 언제든지 동적으로 필요한 시점에 데이터를 저장할 수 있다는 것을 의미한다.(이러한 의미에서 Elasticsearch와 Solr 같은 검색엔진(색인)도 일종의 NoSQL이라 불리지 않을 까 싶다. 실제 샤딩,복제 등의 기능도 대부분의 검색엔진 솔루션 자체적으로 지원해준다.) 하지만 MongoDB는 모든 부분에 있어서 스키마 프리라고는 보기 힘들다. 다른 NoSQL 데이터베이스와는 달리 보조 인덱스를 생성할 수 있는데, MongoDB의 보조 인덱스는 항상 먼저 인덱스를 구성하는 필드를 먼저 정의해야 한다.

 

이외의 MongoDB의 특징과 장단점들이다.

 

<특징>

 

  • Document-oriented storage : MongoDB는 database > collections > documents 구조로 document는 key-value형태의 BSON(Binary JSON)으로 되어있다.
  • Full Index Support : 다양한 인덱싱을 제공한다.
    • Single Field Indexes : 기본적인 인덱스 타입
    • Compound Indexes : RDBMS의 복합인덱스 같은 거
    • Multikey Indexes : Array에 미챙되는 값이 하나라도 있으면 인덱스에 추가하는 멀티키 인덱스
    • Geospatial Indexes and Queries : 위치기반 인덱스와 쿼리
    • Text Indexes : String에도 인덱싱이 가능
    • Hashed Index : Btree 인덱스가 아닌 Hash 타입의 인덱스도 사용 가능
  • Replication& High Availability : 간단한 설정만으로도 데이터 복제를 지원. 가용성 향상.
  • Auto-Sharding : MongoDB는 처음부터 자동으로 데이터를 분산하여 저장하며, 하나의 컬렉션처럼 사용할 수 있게 해준다. 수평적 확장 가능
  • Querying(documented-based query) : 다양한 종류의 쿼리문 지원. (필터링, 수집, 정렬, 정규표현식 등)
  • Fast In-Pace Updates : 고성능의 atomic operation을 지원
  • Map/Reduce : 맵리듀스를 지원.(map과 reduce 함수의 조합을 통해 분산/병렬 시스템 운용 지원, 하둡처럼 MR전용시스템에 비해서는 성능이 떨어진다)
  • GridFS : 분산파일 저장을 MongoDB가 자동으로 해준다. 실제 파일이 어디에 저장되어 있는지 신경 쓸 필요가 없고 복구도 자동이다.
  • Commercial Support : 10gen에서 관리하는 오픈소스

<장점>

  • Flexibility : Schema-less라서 어떤 형태의 데이터라도 저장할 수 있다.
  • Performance : Read & Write 성능이 뛰어나다. 캐싱이나 많은 트래픽을 감당할 때 써도 좋다.
  • Scalability : 애초부터 스케일아웃 구조를 채택해서 쉽게 운용가능하다. Auto sharding 지원
  • Deep Query ability : 문서지향적 Query Language 를 사용하여 SQL 만큼 강력한 Query 성능을 제공한다.
  • Conversion / Mapping : JSON형태로 저장이 가능해서 직관적이고 개발이 편리하다.

<단점>

 

  • JOIN이 없다. join이 필요없도록 데이터 구조화 필요
  • memory mapped file으로 파일 엔진 DB이다. 메모리 관리를 OS에게 위임한다. 메모리에 의존적, 메모리 크기가 성능을 좌우한다. 2-4를 참고하자.
  • SQL을 완전히 이전할 수는 없다.
  • B트리 인덱스를 사용하여 인덱스를 생성하는데, B트리는 크기가 커질수록 새로운 데이터를 입력하거나 삭제할 때 성능이 저하된다. 이런 B트리의 특성 때문에 데이터를 넣어두면 변하지않고 정보를 조회하는 데에 적합하다.

 

MongoDB의 Physical 데이터 저장구조

MongoDB를 구성할 때 보면, 가장 많이 이슈되는 부분 중 하나가 메모리량과 디스크 성능이다. 메모리 크기가 아주 민감한 요인이 된다. 

 

MongoDB는 기본적으로 memory mapped file(OS에서 제공되는 mmap을 사용)을 사용한다. 데이터를 쓰기할때, 디스크에 바로 쓰기작업을 하는 것이 아니라 논리적으로 memory 공간에 쓰기를 하고, 일정 주기에 따라서, 이 메모리 block들을 주기적으로 디스크에 쓰기한다. 이 디스크 쓰기 작업은 OS에 의해서 이루어 진다.

 

OS에 의해서 제공되는 가상 메모리를 사용하게 되는데, 물리 메모리 양이 작더라도 가상 메모리는 훨씬 큰 공간을 가질 수 있다. 가상 메모리는 페이지(Page)라는 블럭 단위로 나뉘어 지고, 이 블럭들은 디스크 블럭에 매핑되고, 이 블럭들의 집합이 하나의 데이터 파일이 된다.

 

 

메모리에 저장되는 내용은 실제 데이터 블록과, 인덱스 자체가 저장된다. MongoDB에서 인덱스를 남용하지 말라는 이야기가 있는데, 이는 인덱스를 생성 및 업데이트 하는데 자원이 들어갈 뿐더러, 인덱스가 메모리에 상주하고 있어야 제대로 된 성능을 낼 수 있기 때문이기도 하다.

 

만약에 물리 메모리에 해당 데이터 블록이 없다면, 페이지 폴트가 발생하게 되고, 디스크에서 그 데이터 블록을 로드하게 된다. 물론 그 데이터 블록을 로드하기 위해서는 다른 데이터 블록을 디스크에 써야한다.

 

즉, 페이지 폴트가 발생하면, 페이지를 메모리와 디스카 사이에 스위칭하는 현상이 일어나기 때문에 디스크IO가 발생하고 성능 저하를 유발하게 된다.

 

즉 메모리 용량을 최대한 크게 해서 이 페이지폴트를 예방하라는 이야기이다. 그러나, 페이지 폴트가 아예 발생 안할 수는 없다.(1TB의 데이터를 위해 메모리를 진짜 1TB만큼 올릴 수는 없다.) 그래서 페이지 폴트를 줄이는 전략으로 접근 하는 것이 옳은 방법이다.

 

페이지 폴트시 디스크로 write되는 데이터는 LRU 로직에 의해서 결정된다. 그래서, 자주 안쓰는 데이터가 disk로 out되는데, 일반적인 애플리케이션에서 자주 쓰는 데이터의 비율은 그리 크지 않다. 이렇게 자주 액세스되는 데이터를 Hot Data라고 하는데, 이 데이터들이 집중되서 메모리에 올라가도록 Key 설계를 하는 것이 핵심이다. 전체 데이터를 scan하는 등의 작업을 하게 되면, 무조건 페이지 폴트가 발생하기에 table scan이 필요한 시나리오는 별도의 index table(summary table)을 만들어서 사용하는 등의 전략이 필요하다.

 

MongoDB 배포 형태별 아키텍쳐

 

1)단일 노드

단일 노드로 MongoDB를 사용할 때에는 아무런 관리용 컴포넌트도 필요하지 않다. 클라이언트는 MongoDB 클라이언트 드라이버와 통신하며 MongoDB 클라이언트 드라이버는 1:1로 MongoDB 서버와 통신한다.

 

2)단일 레플리카 셋

레플리카 셋은 특정 서버에 장애가 발생했을 때, 자동 복구를 위한 최소 단위이므로 자동 복구가 필요하다면 항상 레플리카 셋으로 배포해야 한다. MongoDB 클라이언트 드라이버는 직접 MongoDB 서버로 접속하지만, 단일 노드로 접속할 때와 달리 레플리카 셋 옵션을 사용해야 한다. 하나의 레플리카 셋에는 항상 하나의 프라이머리 노드와 1개 이상의 세컨드리 노드로 구성되며, 프라이머리 노드는 사용자의 데이터 변경 요청을 받아서 처리하고, 세컨드리 노드는 프라이머리 노드로부터 변경 내용을 전달받아서 서로의 데이터를 동기화한다. 읽기 쿼리는 프라이머리 노드뿐만 아니라 필요하면 세컨드리 노드로 요청할 수 있다.

 

MongoDB 레플리카 셋은 항상 레플리카 셋에 포함된 노드 간 투표를 통해서 프라이머리 노드를 결정하므로 가능하면 홀수 개의 노드로 구성하는 것이 좋다. 짝수 개의 노드로도 구성할 수 있지만, 실제 홀수로 구성한 것과 가용성이 다르지 않으며 오히려 하나의 노드가 낭비된다. 또한 짝수로 구성하면 쿼럼 구성이 어려워질 수도 있다.

 

하지만 이런 생각을 할 수 있다. "레플리카 셋을 굳이 3대의 서버로 구축하는 것은 때로는 서버의 낭비일 수 있지 않나?" 이런 경우를 위해서 MongoDB서버를 아비터 모드로 실행할 수 있다. 아비터 모드로 시작되면 레플리카 셋의 노드들과 하트비트만 주고 받으며, 프라이머리 노드가 불능일 때, 아비터 모드가 아닌 세컨드리 노드중에 프라이머리 노드의 선출을 위한 투표에만 참여한다. 아비터는 로컬 디스크에 데이터를 저장하지 않고 프라이머리부터 데이터를 주고 받지 않기 때문에 고 사양의 장비가 필요하지 않다. 또한 아비터는 데이터를 가지고 있지 않으므로 프라이머리 노드로 선출될 수도 없다. 하나의 레플리카 셋에 여러개의 아비터 노드가 존재할 수는 있지만, 실제 정상적인 상태에서 하나 이상의 아비터는 필요하지 않다.

 

3)샤딩된 클러스터

샤딩된 클러스터 구조에서는 하나 이상의 레플리카 셋이 필요하며, 각 레플리카 셋은 자신만의 파티션된 데이터를 가지게 된다.(예를 들면 전체 데이터가 6이고, 레플리카 셋이 3개라면 각각 2의 데이터 파티션을 나누어 갖는다.) 샤딩된 클러스터에 참여하고 있는 각각의 레플리카 셋을 샤드라고 하는데, 이 샤드들이 어떤 데이터를 가지는지에 대한 정보는 MongoDB 컨피그(Config) 서버가 관리한다.

 

샤딩된 클러스터 구조에서는 위의 2가지 상황과 달리 MongoDB 클라이언트 드라이버가 직접 서버에 붙지 않고 MongoDB 라우터(mongos)에 연결된다. 그리고 라우터는 자동으로 MongoDB 컨피그 서버로부터 각 샤드가 가지고 있는 데이터에 대한 메타 정보들을 참조하여 쿼리를 실행한다. 말 그대로 라우터(mongos)는 사용자로부터 요청된 쿼리를 실제 데이터를 가지고 있는 샤드로 전달하는 역할을 수행한다. 하지만 이뿐만 아니라 라우터는 사용자를 대신하여 모든 샤드로부터 쿼리를 요청하고 결과를 정렬 및 병합해서 반환하는 처리도 수행한다. 라우터는 각 샤드간의 데이터가 재분배되는 시점에도 동일한 역할을 수행하여 사용자나 응용 프로그램이 알아채지 못하게 투명하게 데이터 리밸런싱 작업을 처리한다.

 

여기까지 간단하게 MongoDB에 대해 이론적인 내용으로 살펴보았다. 나만 느끼는 건지 모르겠는데, 분산처리,샤딩,복제 등을 지원하는 모든 솔루션들은 대부분 아키텍쳐가 비슷한 느낌이다.

 

 

 

MongoDB (RDB와 비교, 특징과 장단점, 메모리성능 이슈, 주요용어)

참조문서 : https://docs.mongodb.com/ mongoDB는 C++로 짜여진 오픈소스 데이터베이스이다. 문서지향(Document-Oriented)적이며 뛰어난 확장성과 성능을 자랑한다. NoSQL이다. 1. RDB와 비교 RDBMS MongoDB Datab..

sjh836.tistory.com

 

MongoDB의 Physical 데이타 저장 구조

MongoDB를 구성할때 보면, 가장 많이 권장 받는 부분 중의 하나가, 메모리량과 디스크 성능이다. 메모리 크기가 아주 sensitive한 요인이 되는데, 어떤 부분이 문제가 되는지 내부 저장 구조를 살펴 봄으로써 이해..

bcho.tistory.com

 

posted by 여성게
:
Middleware/Redis 2019. 2. 27. 23:56

Redis - Sentinel 이란? 설정방법! Redis 고가용성을 위한 방법




이전 포스팅에서 Redis Server Replication 구성방법에 대해 알아봤습니다. 이번 포스팅은

Redis 고가용성을 위한 Sentinel 기능에 대해 알아보려고 합니다. 어떻게 보면 조금더 완벽한 클러스터링을

구성한다고 생각하시면 됩니다. 


만약 Redis 설치 및 설정 방법을 모르신다면 아래 링크를 통해 참조하시고 오셔도 좋을 것같습니다.

▶︎▶︎▶︎Redis 설치 및 설정, 간단한 사용법!


우선 Sentinel에 대한 기능에 대해 알아보겠습니다.


1) 모니터링

2) 알림기능

3) 페일오버

4) 환경 구성 프로바이더


이러한 기능을 제공해줍니다.



오늘 예제로 구성해볼 이미지입니다.



구성이 이해가 가십니까? 간단하게 설명을 하면 Master&Slave는 이전 포스팅과 동일하게 3개의 노드를 띄웁니다.

그리고 Sentinel도 동일하게 3개의 노드를 띄웁니다(3개의 의미가 있음). 이런 구성에서 Sentinel은 마스터를 지속적으로 

모니터링합니다. 그리고 장애가 있을시에 적당한 프로세스를 거칩니다. 여기서 Sentinel의 노드를 3개를 띄웠는데요. 이것은

의미가 있는 숫자입니다. 이전에 포스팅 중 Zookeeper관련된 글에서도 동일한 정책을 따랐는데요. 


"바로 홀수단위로 띄운다"


입니다. 이것은 만약 네트워크의 잠깐의 오버타임때문에 마스터가 죽었다고 생각하는 하나의 Sentinel이 있을 수 있습니다.

그럼 이것이 진짜로 죽은 거라고 판단을 해야할까요? 우리는 보통 선거를 하게되면 과반수의 원칙에 따르게 됩니다. 여기서도

동일하게 과반수의 원칙을 따르게 되는 겁니다. 과반수 이상의 Sentinel이 "OK" 해야 비로소 그 마스터 노드는

죽은 것이고, 그때서야 Slave 노드에서 마스터 노드를 선출하게 되는 것입니다. 그렇기 때문에 Sentinel은

3개이상의 홀수 인스턴스를 띄운다 원칙을 지켜주셔야합니다.


우리가 구성할 실제 구성도입니다.



진행하기 앞서, $REDIS(Redis 폴더 root)에 있는 sentinel.conf 파일을 2개 복사해줍니다.(총 3개의 Sentinel 설정파일 구성)

그리고 아래 설정을 port만 각기 분리해주고 나머지 설정을 동일하게 작성해줍니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 11001.conf ~ 11003.conf
 
# 센티널이 실행될 포트입니다. (이부분은 포트별로 다르게 설정)
port 11001
# 센티널이 감시할 레디스 Master 인스턴스 정보를 넣어줍니다.
# sentinel monitor mymaster <redis master host> <redis master port> <quorum>
sentinel monitor mymaster 127.0.0.1 10000 2
# 센티널이 Master 인스턴스에 접속하기 위한 패스워드를 넣어줍니다.
sentinel auth-pass mymaster foobared
# 센티널이 Master 인스턴스와 접속이 끊겼다는 것을 알기 위한 최소한의 시간입니다.
sentinel down-after-milliseconds mymaster 30000
# 페일오버 작업 시간의 타임오버 시간을 정합니다.
# 기본값은 3분입니다.
sentinel failover-timeout mymaster 180000
# 이 값은 Master로부터 동기화 할 수 있는 slave의 개수를 지정합니다.
# 값이 클수록 Master에 부하가 가중됩니다.
# 값이 1이라면 Slave는 한대씩 Master와 동기화를 진행합니다.
sentinel parallel-syncs mymaster 1
cs


여기서 하나 설명할 것이 있다면 설정중 quorum 입니다. 이것은 의사결정에 필요한 최소 Sentinel 노드수라고 생각하시면 됩니다.

즉, 지금 구성에서는 딱 과반수가되는 2개의 Sentinel이 동의하면 의사결정이 진행이 되는 것입니다.


SDOWN vs ODOWN

More advanced concepts이라는 페이지에서 SDOWN과 ODOWN이라는 단어가 나옵니다. SDOWN은 Subjectively Down condition의 축약어이고 ODOWN은 Objectively Down condition의 축약어입니다.

SDOWN은 센티널 인스턴스가 Master와 접속이 끊긴 경우 주관적인 다운 상태로 바뀝니다. 이것은 잠시 네트워크 순단 등으로 인해 일시적인 현상일 수 있으므로 우선 SDOWN 상태가 됩니다.

그러나 SDOWN 상태인 센티널들이 많아진다면 이는 ODOWN 상태(quorum), 즉 객관적인 다운 상태로 바뀝니다. 이때부터 실질적인 페일오버(failover) 작업이 시작됩니다.



위의 설정을 모두 완료하셨다면 이전 포스팅에서 진행한 redis.conf를 조금 변경해야합니다.


Redis Server 설정 파일에 마스터,슬래이브 관계없이 모두


masterauth yourpassword

requirepass yourpassword


두개의 설정을 3개의 redis conf에 설정해줍니다. 이유는 슬래이브 노드가 마스터 노드로 선출될 수도 있기에

모든 슬래이브는 require pass 설정을 가져야하고 마스터 노드도 슬래이브 노드가 될수 있기 때문에

masterauth설정을 해주어야합니다.


이제 실행을 해봅니다. Redis Server들은 이전 포스팅에서 진행한 데로 실행해주시면 됩니다.


>$REDIS/src/redis-sentinel ../sentinel.conf

>$REDIS/src/redis-sentinel ../sentinel2.conf

>$REDIS/src/redis-sentinel ../sentinel3.conf


명령으로 모든 센티널들을 실행시킵니다.



로그를 하나하나 설명안해도 읽어보시면 어떠한 로그인지 직관적으로 이해가갑니다.



여기에서 마스터 노드를 shutdown 시켜봅니다. 그리고 마스터 선출에 시간이 걸리니 대략

30초 정도 기다려봅니다. 아니? 슬래이브 노드가 마스터노드로 선출됬습니다.



기존에 마스터였던 6379는 슬래이브로, 기존에 슬래이브였던 6381이 마스터로 선출되었습니다.

위의 정보를 출력하기 위해서는 


>./redis-cli -p port -a password

>info


로 접속하셔야합니다. 패스워드를 작성안하시면 해당 명령어를 사용하실수 없습니다.


여기까지 Redis Server 고가용성을 위한 Sentinel 구성이었습니다. production 환경에서는 반드시

위와같이 장애에 대응할 수 있는 서버 구성을 가져야합니다. 


다음 포스팅은 실제 Redis를 Springboot에서 추상화된 객체로 사용해보는 예제를 진행 해볼 것입니다.

posted by 여성게
:
Middleware/Redis 2019. 2. 27. 23:01

Redis - Redis 설치 및 설정, 간단한 사용방법




Redis란? 정말 단순하게 표현하면 key-value 형태의 값을 저장할 수 있는 하나의 In-Memory DB라고 생각하시면 됩니다. 

사용용도는 정말 많습니다. Springboot에서는 세션클러스터링을 위해 Redis를 사용하기도 하고, Cache를 위해서 사용하기도 하며,

여러 서버에서 공통으로 공유해야하는 정보를 담는 용도로 사용하기도 합니다. 필자는 챗봇을 개발중인데, 이중화된 서버에서 세션값을

공유하기위한 용도로 Redis를 사용하려고 합니다. 우선 이번 포스팅에서는 Redis 설치 및 설정, 그리고 간단한 사용법에 대한 포스팅입니다.


▶︎▶︎▶︎Redis Homepage


우선 위에서 Redis를 다운로드 받아줍니다.


그리고 다운로드 받아진 Redis Root 폴더로 들어가서

>make 

명령으로 컴파일을 해줍니다.


준비끝 !



첫번째 예제는 Redis Server를 Standard Alone으로 구성하는 예제입니다.

(편의상 Redis 폴더의 root를 $REDIS로 표현합니다.)


>$REDIS/src/redis-server 


위처럼 실행시켜줍니다. 그러면 Redis Server은 모든 기본설정으로 구동이됩니다.

localhost:6379



이런 화면이 보인다면 지금까지는 잘 따라오신겁니다. 다음은 cli를 이용하여 간단하게 데이터를 삽입,조회 해보겠습니다.



직관적으로 key-value 형태의 데이터를 삽입하고 조회하는 예제입니다.


현재까지의 구성으로 dev환경에서는 충분히 활용가치가 있습니다. 하지만 prod환경에서는 하나의 Redis Server로

운영한다는 것은 아주 위험한 선택일 것 같습니다. 그래서 다음 예제는 Zookeeper와 같은 소프트웨어에서도 이용하는

구성인 Master-Slave 관계를 구축해보겠습니다. Redis Server 구성은 하나의 로컬에서 구성한다는 가정입니다.



서버명 

IP:PORT 

Master Node 

127.0.0.1 : 6379 

Slave Node - 1 

127.0.0.1 : 6380 

Slave Node - 2 

127.0.0.1 : 6381 


위의 구성으로 진행해보도록 하겠습니다. 진행하기에 앞서 우리가 이번 포스팅에서 건들게되는 

설정파일이 있습니다. 그것은 바로 redis.conf입니다. 해당 파일을 들어가보면 주석으로 친절하게 설정정보 설명이 되어있습니다.

이번에는 모든 설정정보를 다루기보다는 우리가 많이 다루고, 꼭 필요한 정보들에 대한 설명만 할 예정입니다.


우선 다중 Redis Server 구성을 위하여 $REDIS에 있는 redis.conf를 2개 복사해둡니다.(Slave 2개 설정파일)


>cp redis.conf ./redis-slave1.conf

>cp redis.conf ./redis-slave2.conf


설정값

설명 

daemonize [yes||no] default no 

Redis는 기본적으로 daemon으로 실행하지 않습니다. 만약 daemon으로 실행하고 싶다면 'yes'를 사용하시면 됩니다. 만약 daemon으로 실행시 '/var/run/redis.pid' 파일에 pid를 디폴트로 기록할 것입니다.(파일경로 변경가능 - pidfile 설정) 

port [number] default 6379 

Connection 요청을 받을 포트를 지정하는 설정입니다. 

bind [ip] default all interface

Redis를 bind 할 특정 interface를 지정하는 설정입니다. 만약 명시하지 않으면 모든 interface로부터 들어오는 요청들을 listen합니다. 

unixsocket [path], unixsocketperm [number]

unixsocket /tmp/redis.sock / unixsocketperm 755

소켓으로 Redis Server를 붙게할 수 있는 설정입니다. 

timeout [second] 

클라이언트의 idle 시간이 해당 초만큼 지속되면 connection을 닫습니다.

0으로 지정할시 항상 connection을 열어둡니다. 

loglevel [level - debug, verbose,notice,warning] 

로그레벨지정 

logfile [file path] 

로그파일이 쓰여질 파일 경로를 지정합니다. 

slaveof -> replicaof [master ip] [master port] 

최근 버젼은 slaveof에서 replicaof로 변경됨.(어느 버전부터 바뀐지는 확인필요)

Master-Slave 관계를 구성하기 위하여 Master의 replication Node가될 slave Node 설정파일에 Master Node의 ip와port 정보를 기입하는 설정이다.

즉, Master의 데이터가 slave에 replicate되게 된다. 

 masterauth [master-password]

만약 Master Node 설정파일에 Slave Node가 붙기 위한 암호요구를 하였다면(require pass [password]), Slave Node의 설정파일은 Master Node가 지정한 패스워드로 해당 설정을 해줘야한다. 

slave-server-stale-data [yes||no] default yes

-> replica-server-stale-data [yes||no] default yes 

만약 slave가 master와의 connection이 끊겼거나 replication 중일 때, 취할수 있는 행동 2가지가 있다.


1. [yes] - 유효하지 않은 데이터로 클라이언트 요청에 답한다.

2. [no] - 몇몇 명령을 제외하고 요청에 대해 error로 응답한다. 

repl-ping-slave-perid [seconds] default 10 

Slave가 지정된 시간마다 ping을 날린다. 

repl-timeout [seconds] default 60 

타임아웃 시간을 설정한다. 기본적으로 ping 주기보다 큰 시간을 주어야한다. 

 require pass [password]

클라이언트에게 패스워드를 요구한다.(Slave가 Master에 접근할때의 보안설정이기도하다) 

maxclient [size]

한번에 연결될 수 있는 클라이언트의 연결수이다. 

maxmemory [bytes] 

Redis Server의 최대 메모리 사용양을 설정한다. 만약 memory에 한계가 도달했다면 Redis는 선택된 eviction policy(제거정책)에 따라 key들을 제거한다. 만약 제거에 실패한다면 read-only에 대한 명령만 수행할 수있게 된다. 

maxmemory-policy [policy] 

max memory 도달시 취할 정책을 설정한다

1) volatile-ru : expire가 설정된 key들 중 LRU 알고리즘을 이용해 선택된 key를 제거한다.

2) alleys-lru :  모든 keys에 대해 LRU 알고리즘을 적용해 제거한다.

3) volatile-random : expire가 설정된 key들 중 임의의 key를 제거한다.

4) alleys-random : 모든 keys중 랜덤하게 제거한다.

5) volatile-ttl : expire time이 가장 적게 남은 key를 제거한다.

6) noeviction : 어떠한 key도 제거하지 않는다. read-only작업만 허용하고 write와 그 밖에 명령은 error를 내뿜는다.

appendonly [yes||no]

Redis는 기본적으로 비동기로 disk에 dataset의 dump를 남긴다. 이 방법은 최근 데이터가 손실되어도 큰 문제가 없다면 사용해도 좋지만, 하나라도 데이터의 유실을 원치 않는 상황이라면 yes로 설정하여 요청받는 모든 write를 disk에 쓰도록하면 된다.(default file appendonly.aof) 

 appendfilename [file name]

append only 파일 이름을 설정한다. 


여기까지 몇가지 설정들을 다루어봤다. 실제 위에 설정들 일부를 사용하여 Master-Slave 관계를 구성해볼 것이다.


우선 MasterNode의 설정파일로 사용할 redis.conf이다.


>bind 127.0.0.1

>port 6379

>requirepass yourpassword

>daemonize  yes


이정도 설정으로 나머지는 기본설정을 사용한다.


이제는 나머지 SlaveNode의 설정파일 2개이다.


>bind 127.0.0.1

>port 6380(slave -1) / port 6381(slave-2)

>replicaof 127.0.0.1 6379

>masterauth yourpassword

>daemonize yes


로 구성한다.



이제 순차적으로 실행시켜본다


>$REDIS/src/redis-server ../redis.conf

>$REDIS/src/redis-server ../redis-slave1.conf

>$REDIS/src/redis-server ../redis-slave2.conf



Master&Slave를 순차적으로 실행 시킨 로그이다. Connection이 맺어지고 있는 것이 보인다.


그리고 실제로 데이터의 복제가 잘 이루어지는지 보기 위해 몇개의 창을 더 띄워서

cli로 데이터를 삽입,조회해본다.



복사가 잘된것을 확인할 수 있다. 그렇다면 혹시나 Master와의 관계를 끊기 위해

Master 노드를 중지시켰다면 어떻게 될까?



SlaveNode들의 로그를 보면 connection refused 로그가 계속해서 떨어진다.

하지만 아까 보았던 설정에서 replica-server-stale-data의 설정에 따라 Slave들의 행동이 

달라질것이다.



마지막으로 다시 MasterNode를 띄워보면



Slave들이 다시 Master에 connection 된것을 볼수있다. 여기까지는 좋다. 데이터 복제를 위해 replica도 구성했고,

근데 하나찜찜한 것이있다. Master가 죽으면 알아서 Slave중에서 Master를 선출하면 좋을 텐데.... 방법이 있다!

바로 sentinel을 이용하여 클러스터를 구성해주는 것이다. sentinel은 아쉽게도 다음 포스팅에서 다뤄볼 예정이다.


posted by 여성게
: