반응형

Logical Session 에 대해서 정리 하였습니다.

한글로 된 자료도 많지가 않아서 초등이하 수준의 영어를 번역기 돌리고 나쁜 머리로 이해하고 쓰느라 부족한 부분이 많습니다. 부디 저의 글이 도움이 되어, 보다 자세하고 정확한 글들이 나오길 기대하는 마음으로 작성하였습니다.

 

 

Logical Session
  • server session 또는 logical session 은 클라이언트에서 Causal Consistency 와 다시 쓰기 시도(retryable write)와 같은 기본 프레임 워크를 지원
  • Logical session(식별자)을 생성함으로써, single operation 또는 multiple-operation transaction에서 사용되는 리소스를 추적이 가능
    • 이러한 프레임 워크를 이용하여 Transaction 을 구현이 가능
    • Logical session 과 Logical session Identifier(식별자) 를 만드는데, 이것을 lsid라고 하고 lsid는 유니크한 값으로 mongodb cluster와 client간 연결
    • MongoDB 3.6이후로는 client 조작은 모두 logical session 과 연관되며, lsid가 클러스터 전체에서 명령어의 조작과 관련
    • lsid를 이용하여 특정 lsid 를 식별하는게 쉬워지고 전체 프로세스가 단순해 짐
    • 컨트롤러 프로세스가 연결된 lsid를 5분마다 수집하고 30분 후에 트리거되는 ttl 인덱스를 이용하여 30분간 재사용 되지 않는 session에 대해서는 리소스 정리가 가능
  • application 은 client session 을 이용하여 server session 을 이용
    • server session 은 replica set / sharded cluster 에서만 사용 가능
option
type
description
lsid
Document
명령을 실행하는 session 의 고유 ID(GUID-Global Unique ID)를 지정
  • MongoDB Client에 의해 자동으로 생성
txnNumber 는 lsid 가 반드시 필요
txnNumber
64 bit integer
명령 세션에서 명령을 고유하게 식별하는 양수
lsid 옵션도 함께 필요
cf) RDBMS 는?
단일노드에서 읽기 및 쓰기를 서비스하기 때문에 자연스럽게 Casual Consistency 으로 알려진 읽기 및 쓰기 작업에 대한 순차적 순서 보증을 제공
하지만 분산 시스템은 이러한 보증을 제공할 수 있지만 이렇게 하기 위해서 모든 노드에서 관련 이벤트를 조정하고 정렬해야 특정 작업이 완료 될 수 있는 속도를 제한 필요
Casual Consistency 는 모든 데이터 순서 보증이 유지되는 경우를 이해하는 것이 가장 쉽지만, 시스템이 노드 충돌이나 네트워크 파티션과 같은 장애에 직면할 때에도 시스템이 해야 할 많은 일관성과 내구성 트레이드 오프가 존재
 
Causal Consistency
  • v3.6
  • 인과적 일관성이라고 번역
  • 읽기 쓰기 등이 순차적 순서를 보장하는 것을 의미
    • 연산이 앞선 연산에 논리적인 의존성을 가지는 경우(동일한 데이터에 접근), 이 두 연산은 causal relationship을 가졌다고 표현
    • 이때, 클라이언트 어플리케이션에서는 반드시 한번에 한 쓰레드만이 이 연산들을 시도하도록 보장해야만 함
  • 일관성을 보장하기 위한 작업을 의미
  • Write / Read Concern 이 모두 majority 가 casual consistency 를 보장
  • 참고로 분산 시스템에 대한 일반적인 데이터 개념 (단순 Mongodb만 해당 하는 것이 아님)
    • 주요 memory 일관성 모델 중 하나
    • 공유 메모리에 접근하는 프로그래밍에서 일관성 모델은 어떤 access 가 정확한 순서인지를 제한
    • 분산 공유 메모리 또는 분산 트랜잭션에서 올바른 데이터 구조를 정의하는데 유용
  • 분산시스템이 Scale up/down 만 가능한 DBMS를 모방한 작업 순서를 보장 기능
  • majority 를 이용하여 읽기, 쓰기에 대한 완전한 일관성을 보장하지만, 사용 사례로 다양하게 사용 가능
  • Causal Consistency는 read / write 어떤 연산을 수행과 상관없이 동작하는데 이 때 비용이 발생하기에,  단조적 읽기 보장(monotonic read guarantees)이 필요한 곳에만 사용함으로써 causal consistency에 의한 지연을 최소화할 수 있음
  • 반드시 아래 내용 해석 정리 필요
read your writes
read operations reflect the results of write operations that precede them
(읽기 작업은 앞에 있는 쓰기 작업의 결과를 반영합니다.)
 
Monotonic reads
(단조로운 읽기)
Read operations do not return results that correspond to an earlier state of the data than a preceding read operation.
읽기 작업은 이전 읽기 작업보다 이전 데이터 상태에 해당하는 결과를 반환하지 않습니다.
Monotonic write
(단조로운 쓰기)
Write operations that must precede other writes are executed before those other writes.
다른 쓰기보다 선행되어야 하는 쓰기 작업은 해당 다른 쓰기보다 먼저 실행됩니다.
Writes follow reads
읽기 다음 쓰기
Write operations that must occur after read operations are executed after those read operations.
쓰기 작업은  읽기 작업 후에 발생해야 합니다,
  • Casual Consistency 가 없는 경우
    • 전제 사항으로 읽기작업은 secondary에서 진행하기 때문에, Primary 에 쓰기 작업 이후 바로 secondary에서 읽을 때 Write가 성공 되었다고 하지만, 복제 보다 먼저 read를 요청하여 write 작업이 반영 안된 현상 발생
    • 단순히 replica set 을 예를 들었지만, Sharded cluster 에서도 동일한 문제가 발생 가능

  • Casual Consistency 가 없는 경우 해결방법
    • Lamport logical clock 을 기반으로 하이브리드 logical clock 을 구현
    • Primary에서 write 되는 이벤트에는 primary 시간이 할당
    • primary 시간은 모든 구성원 노드가 해당 시간으로 비교 진행
    • 모든 DML(write)에 대해서는 각각의 최신 시간을 할당하고, 해당 시간으로 구성원 노드들이 비교하여 순서를 따져 작업 진행

 

 
Write and read concerns
  • Write Concern / Read Concern 은  Casually consistent 작업 집합 내, 각 작업에 적용할 수 있는 설정
  • Write concern에는 latency와 durabillity (내구성) 중 하나를 선택
  • Read Concern 의 경우 isolation level과 연관이 있음(commit 된 snapshot 에 반영된 데이터를 이용)
  • 이러한 작업들은 모두 시스템 장애 시 데이터 보존에 영향(read / write concern)
  • 여러 샤드에서 transaction 일 때, transaction 에서 변경 중인 데이터라고 transaction 외부에서 해당 데이터를 무조건 볼수 없는 것이 아닌, read concern이 local인 경우, 특정 샤드 내 커밋된 데이터는 볼 수 있음 (Transaction 내 A, B 샤드에 걸쳐서 write 가 발생 중인데, 이 때 A는 commit 되고, B에서는 commit 되기 전이라면, A의 commit 된 데이터는 read concern 이 local 상황에서 조회가 가능)
  • 테스트 시나리오

테스트 시나리오

Read Concern majority with Write Concern majority

  • W1 의 Majority Write 작업이 모두 완료 될 때까지, R1는 기다려야함.
    • W1의 작업이 완료된 내역을 Read 하기 때문에 R1는 W1 의 결과값을 반환
  • 혹시라도 장애가 발생하더라도, 데이터는 보장받기 때문에 속도가 느린 대신 예기치 않은 장애에도 정상적인 데이터를 반환하기 때문에 금융 어플리케이션 같인 주문 거래 등에서 일관성 / 내구성을 모두 확보하기 때문에 활용 가능

Read Concern majority with Write Concern majority

Read Concern majority with Write Concern 1

  • W1은 primary에만 성공하면 완료 되기 때문에, w1이 rollaback 되더라도 P1, P2 모두 정상적인 데이터 결과 제공
  • R1은 Majority이기 때문에 T1-W1 작업이 각 secondary에 전파되어 과반수 commit 될 때까지 기다렸다가 정상적이 데이터 확인
  • 단, p1 같이 primary가 failover 발생 시 , w1는 primary에만 작성하니 성공적으로 끝나지만, Read majority - R1는 과반수로 전파가 되지 않았기 때문에 읽을 수 없음을 의미
  • 장애가 발생할 경우 내구성을 보장하지 않지만, casual 한 순서만 보장

Read Concern majority with Write Concern 1

  • 사용자 기반에 신속하게 서비스를 제공해야 하는 대규모 플랫폼에 고려.(높은 처리량 트래픽을 관리하고 짧은 대기 시간 요청의 이점, 방금 write한 것은 지연 또는 rollback 이 발생할 수 있기 때문에 글 작성한 유저 등은 일시적으로 아래와 같이 회색 처리하여 write 가 끝나지 않음을 간접적으로 제공)

 


Read Concern local with Write Concern majority

  • Write Concern majority 이기 때문에 과반수 노드에 저장
  • Read 가 local 이기 때문에 P1, P2에서  W1의 commit 되지 않은 데이터를 모두 읽기 가능
    • "read your own writes" 보장이 깨지는 현상 발생
    • p1, p2에서 여러개의 읽기가 순차적으로 실행 되는 단조로운 경우에도 읽기 순서가 보장되지 않음
    • 장애 발생 시 정상적인 데이터가 인과적 보장이 유지되지 않음
  • 다양한 제품, 서비스에 대한 리뷰가 있는 사이트에서 유용
  • 리뷰를 작성하는 내역에 대해서는 확실한 내구성 보장이 유지되면서, 최신 리뷰 또는 실시간 리뷰를 읽을 경우 write 가 majority라 read를 대기하는 그런 현상이 발생하지 않기 때문에 성능상 이점
  • 단, 승인 되지 않은 롤백되는 리뷰도 읽을 수 있는 경우가 발생

Read Concern local with Write Concern majority


Read Concern local with Write Concern 1

  • Write Concern 1이기 때문에 내구성이 부족
    • W1에서 write 후 rollback 하더라도, P2/P1 모두 읽을 수 있음
  • Casual read 인 R1의 경우도 P1, P2에서 모두 읽을 수 있음
    • "read your own writes" 보장이 깨지는 현상 발생
    • p1, p2에서 여러개의 읽기가 순차적으로 실행 되는 단조로운 경우에도 읽기 순서가 보장되지 않음
    • 장애 발생 시 정상적인 데이터가 인과적 보장이 유지되지 않음
  • 스마트 센서 장치 데이터 수집 같은 높은 쓰기 처리량을 유도하는 곳에서 유용
  • 처리량이 높은 워크로드 및 최신성을 선호하는 곳에서 사용

Read Concern local with Write Concern 1



eventual consistency

  • 현재 읽고 있는 데이터가 일관되지 않을 수 있지만 결국 일관성이 유지된다는 의미 (최종 동기화)
  • 적절한 읽기 문제 없이 클러스터 내 다른 구성원이 읽으면 일관성이 보장 되지 않음
  • Secondary에서 readPreference를 사용하여 읽을 경우인데, Primary에서 write 후에 해당 데이터를 secondary 에서 읽을 경우 복제가 완료되지 않아 잘못된 데이터를 읽을 수 있음을 의미
  • 하지만 결국은 복제가 완료 되면 제대로 된 데이터를 읽을 수 있음

테스트 할 수 있는 소스가 있어서 공유

https://github.com/MaBeuLux88/mongodb-3.6-demos/tree/master/4-causal-consistency

 

GitHub - MaBeuLux88/mongodb-3.6-demos

Contribute to MaBeuLux88/mongodb-3.6-demos development by creating an account on GitHub.

github.com

 

Concern / Preference

  • 분산 처리를 기본 아키텍처이기 때문에, 레플리카 셋을 구성하는 멤버들 간의 동기화 제어 가능
  • 데이터를 읽고 쓸 때, 필요한 데이터 동기화 수준에 따라 데이터를 변경, 조회할 수 있도록 read concern / write concern 옵션을 제공
    • 클라이언트에서 쿼리 단위로도 설정 가능
  • 레플리카 셋의 어떤 멤버에게 데이터를 읽을 것인지 설정할 수 있는 read preference 가 존재

Write Concern

  • 데이터의 DML 작업에 대해 동기화 수준을 제어
  • single / multi document transaction 모두 해당
  • 5.0 부터는 majority 가 default / 그전에는 w:1 (primary 만)
  • ACKNOWLDGED(default)
    • 변경 내용을 메모리상에서만 적용하고 바로 client로 성공 또는 실패 응답 반환
    • 동일한 connection 또는 다른 connection 에서 조회 시 변경된 데이터를 메모리 상에서 반환
    • 디스크 동기화는 보장되지 않기 때문에 장애 발생 시 손실 위험이 존재
  • Journal ACKNOWLDGED
    • Journal log (disk) 로 저장하기 때문에 장애 발생시에도 손실 가능성 거의 없음 0.01초?
    • 3.6부터는 Journal log 가 항상 자동으로 active 이기 때문에 ACKNOLDGED 와 차이가 없음
  • Majority
    • 몽고디비는 write 연산이 과반수의 레플리카와 electable 맴버에 적용될 때까지 대기
    • write 연산은 primary election이 이벤트가 발생해도 롤백되지 않으며, primary를 포함하여 여기에 포함된 모든 레플리카들의 journal에 적용됨을 보장

Read Concern

 

Retryable Writes

  • https://www.mongodb.com/docs/manual/core/retryable-reads/#retryable-reads 번역한 내용입니다. 참고하세요.
  • 네트워크 오류가 발생하거나 장애가 발생하여 replication 또는 sharded cluster 의 primary 를 찾을 수 없는 경우 특정 write 작업을 한 번만 자동으로 재시도
    • 네트워크 오류에 대해서는 단 한번만 재시도하며, 지속적으로 네트워크 오류는 해결하지 못함.
    • 장애로 인한 failover 경우
      • Driver 가 serverSelectionTimeoutMS 동안 기다렸다가 재시도
      • 단, 장애조치 시간이 serverSelectionTimeoutMS 초과의 경우 처리하지 않음
      • 클라이언트가 쓰기작업을 실행한 후 localLogicalSessionTimeoutMinutes 이상 응답하지 않을 경우 다시 시작하지 않고, 응답을 시작할 때 쓰기 작업이 재시도 되어 적용
  • 전제 조건
    • Supported Deployment Topologies
      • sharded cluster / replication 환경에서만 되며, standalone 은 해당되지 않음
    • Supported Storage Engine
    • Wiredtiger 엔진 또는 memory storage engine 과 같은 document lock 수준의 storage engine 만 가능
    • 3.6+ MongoDB Drivers
      • 3.6 mongodb driver 이상에서만 지원
    • 4.2 + MongoDB Drivers 
      • Retryable Write 가 enable 이 default (false 로 하고 싶으면 retryWrites=false 로 명시)
  • Retryable Writes and Multi-Document Transactions
    • 4.0
    • Transaction 내에서 commit 또는 rollback 시 write 를 재시도 진행 (Driver 에서 retryWrite 가 false 라고 해도 다시 한번 진행)
    • Trnasaction 내의 각각의 명령어들에대해서는 retryWrite 설정값과 상관없이 개별적으로 재시도는 할 수 없음
  • Retryable Write 명령어
    • https://www.mongodb.com/docs/manual/core/retryable-writes/#retryable-write-operations 참고
    • 4.2 부터 shard key 도 업데이트  가능 (Transaction 내)
    • v4.2 부터 중복 키 예외가 발생한 single document에 대해서는 upsert 를 재시도 (v4.2 이전에는 중복키 오류에 대해서는 upsert 작업을 재시도 하지 않음)
      • upsert retryable write 조건
        • unique index 가 존재
          • unique index 값을 수정하려는 경우는 안됨 (반드시 검색하는 내용이 유니크 값으로 검색해야 함)
          • unique 가 아닌 값으로 검색하는 경우도 해당 되지 않음.
        • singe equality 또는 logical and + equality 명령어 경우

 

Retryable Reads

  • 지원되지 않는 명령어
    • db.collection.mapReduce()
    • getMore
    • database.runCommand 로 실행한 모든 읽기,쓰기 명령어는 지원되지 않음
  • 동작
    • 잦은 네트워크 에러
      • retryable read는 단 한번만 재시도 하기 때문에, 일시적인 네트워크 에러에는 도움이 되나, 영구적인 네트워크 에러는 해결해주지 않음
    • Failover period (failover 발생하는 동안)
      • Driver는 read preference 를 사용하여 read 명령어를 실행
      • 만약 read preference에 의해 read를 하려고 할 때, 재시도할 서버를 선택할 수 없는 경우 오류 발생
      • driver는 serverSelectionTimeoutMS 의 ms 값 만큼 failover 가 완료 될 때까지(정상화) 서버 선택을 기다림
      • serverSelectionTimeoutMS  만큼 기다려도 retryable read를 할 적절한 서버가 없다면 읽기를 처리하지 않음

 

Global Logical Clock

  • https://www.mongodb.com/blog/post/transactions-background-part-4-the-global-logical-clock
  • MongoDB의 동기화를 강화
  • 하이브리드 Logicla Clock 으로 구현되어 암호화로 보호되며, Global Logical Clock 은 Shard Cluster 전체에 걸쳐 동작
  • Multi document ACID Transaction 에서는 Global snapshot을 생성할 수 있으므로, 일관된 global view에서는 시간이 필수.
  • 배경
    • MongoDB의 Clock 은 Shard Mongodb 내 primary oplog 에서 추적
    • 각 작업은, 지속적으로 변경되는 데이터를 oplog 에 저장
    • 각 명령어가 기록되고, primary 와 clock 시간이 logical clock 에 '연결'하고 oplog에 명령어와 함께 저장 (oplog 에 timestamp 뿐만 아니라, logical clock이 함께 연결로 이해)
    • 해당 작업은 oplog에 순서를 제공하고, 샤드 내 모든 노드들에 동기화 하는데 사용
  • 하이브리드 logical clock
    • 샤드 내 노드들만의 자체 clock 이 있을 수 있지만, cluster 내에서는 동작하지 않음
    • clock 은 클러스터 내에서 서로 참조 하지 않는 단순 증가만 할 뿐
    • 3.6에서 구현된 하이브리드 logical clock을 입력하면, 해당 하이브리드 클락은 시스템 시간 뿐만 아니라 동시에 발생하는 명령의 카운터와 결합하여 물리적인 동일한 timestamp를 생성
    • 새로운 timestmp는 클러스터 내 모든 session 에 대해 적용
    • 서버가 timestamp가 포함된 message를 받을 때, 만약 timestamp가 노드의 현재 timestamp 보다 이후이면, timestamp는 최신의 timestamp 값으로 변경 진행되며, 새로운 변경 과 함께 적용된 최신 timestamp로 갱신이 이루어짐
  • 조작 방지
    • 공격자가 시스템에 시간을 조작하여 데이터를 추가를 할 수 있는데, 이 때 최신 timestamp 값 보다 늦은 값이면, 샤드는 이러한 것을 막아 추가가 안되도록 함
    • 해당 문제는 primary의 private key를 이용하여 hash된 timestamp로 생성하여 migration 진행
    • 해당 hash는 timestamp소스가 cluster에 의해 이루어진 verify 내에 있는지 확인용으로 사용되며, 혹시라도 공격자가 private key를 사용할 수 있으면 해당 시스템은 광범위하게 손상이 발생 가능성이 존재
  • Global Logical clock 와 Transaction
    • 하이브리드 Logical Clock을 사용하면 replication 의 여러 노드 및 cluster 의 shard node 간의 쉽게 동기화가 가능
    • Transaction 범위가 4.2 부터 sharded cluster 로 확대되었기에, 신뢰성 높은 clock 동기화가 중요하며 기본이 되어야 가능함
    • Clock 을 조작하기 힘든 것이 신뢰성을 높이는 효과


아직도 추가할 내용이 많음에도 불구하고 대부분 내용들이 번역기를 돌려 이해한 내용들을 바탕으로 작성한 것이라 부족한 부분이 많아 추가하지 못했습니다.

관련된 내용들도 정리하여 추가로 올리도록 하겠습니다.

 

해당 내용들 중에 잘못된 내용들이 있을 수 있으니 참고 정도로만 해주시고, 중간 중간 mongodb 공홈에서 자세한 내용을 읽어 보시면 좋을 듯 합니다.

반응형
반응형

사내 서비스 중 Redis 에서 Lua 를 많이 사용하여 이번 기회에 Lua 메모리 관련하여 정리해 보았습니다.

 

Lua 스크립트란 ?

  • 스크립트 언어로써, 문자열 함수와 수학 함수를 제공
  • 그래픽 시뮬레이션을 위한 스크립트 언어로 개발된 언어로써 타 스크립트 언어보다 빠른 성능을 제공
  • 변수를 제거하거나 미리 선언을 위한 별도의 처리가 필요 없음

 

Redis 에서 Lua 스크립트

  • 프로그래밍 방식 제어구조를 사용하고 db에 access 하여 실행하는 대부분의 명령을 사용 가능
    • redis.call('set', key, value) 형태
  • 지역 변수를 사용해야 함
    • ex) 변수 선언 시 : local src = keys[1]
  • eval 명령어를 이용하여 수행하고자 하는 스크립트를 redis로 전송하여 사용 가능
  • script load 명령을 이용하여 redis server에 등록 시킨 후 사용 가능
    • 데이터가 존재하는 곳에서 실행되기 때문에 전체 대기 시간 뿐만 아니라 네트워크 리소스 절약 가능
    • Application 로직의 일부를 Redis 내에서 실행이 가능하며 여러키에 걸쳐 조건부 업데이트 수행 가능하며 다른 데이터 유형을 함께 처리도 가능
  • Script는 Lua 엔진(Lua5.1) 에 의해 실행
  • 기본적으로 Eval script는 클라이언트 일부로 간주하기 때문에 서버에 persistence 하게(영구) 저장이 되지 않기에(단순 Caching-휘발성), Redis server가 재시작 되거나 한다면 re-Load 해야 함
    • 7.0에서 부터는 redis function 추가 프로그래밍 로직으로 서버 자체를 확장할 수 있는 프로그래밍 가능성에 의해 persitence 하게 저장이 가능 (모든 client에서 사용이 가능)
    • 7.0 부터는 read-only script 가 가능 (read replica에서 지원)
    • https://redis.io/docs/manual/programmability/
  • 메모리 각 내용
    • used_memory_lua :   Lua 엔진에 의해 사용된 메모리 크기 (byte)
    • used_memory_scripts :  5.0 추가   (mh->lua_caches) 생성된 루아 스크립트가 사용하는 메모리 양
      • 모니터링 진행 할 때 used_memory_scripts  를 확인하면 되며, set 명령어만 이루어진 스크립트는 별도로 used_memory_scripts  영역이 변경되지 않음
    • redis server에서 실행되는 lua script는 원자성(Atomicity)하게 처리된다. (lua가 실행되는 동안 다른 레디스 명령어는 실행 안되는 것을 의미-다른 모든 명령어 차단)
      • 이 부분은 single thread 때문이 아닐까...
    • 스크립트 내용이 동일한 동작!!!을 하더라도, 조금이라도 다르다면 다른 스크립트로 인식 하기 때문에, 의미만 변경되는 스크립트 들에 대해서는 변수 처리로 하여 사용하면 캐싱 절약 효과를 얻을 수 있음
#아래는 동일한 동작을 하지만 내용이 다르기 때문에 서로 다른 내용으로 인식하여 used_memory_lua / used_memory_scripts 값 둘다 변경
eval "return 'hellow world?'" 0
eval "return 'hellow world????'" 0

#아래는 동일한 내용을 호출한 경우 캐싱되어 있기 때문에 memory 변화값이 없음을 확인
eval "return 'hellow world????'" 0
eval "return 'hellow world????'" 0

 

테스트 1.

 

이번에는 재밌는 테스트를 진행 하였다.
동일한 redis 구문이지만, return 을 하고 안하고의 차이 이다.
둘다 명령어는 get 명령어로 값을 리턴을 하지만, 이것을 결국 client까지 return을 하느냐 안 하느냐 차이일 것 같은데, 스크립트는 역시 이것을 다른 script로 인식을 하는 것을 확인

eval "redis.call('get', 'lua_test_2555')" 0
eval "return redis.call('get', 'lua_test_2555')" 0
  • 당연히 get 명령어이고 lua script를 호출이기 때문에 used_memory_scripts / used_memory_lua 모두 값이 변경 된 것을 확인할 수 있다.

  • 이번에는 명령어는 동일하지만 return 을 하는 명령어 실행
    • used_memory_scripts / used_memory_lua 모두 값이 변경 된 것을 확인할 수 있다.

  • 당연하겠지만, 기존에 캐싱되어 있는 영역을 다시 조회 시
    • used_memory_scripts / used_memory_lua 모두 값이 변경 되지 않은 것을 확인

  • 결국은 lua 는 내부 모두 동일해야 동일한 script로 인식하여 캐싱 여부를 사용할지 정하는 척도
    • 데이터 변경이 일어나는 곳이라면 당연히 파라메터로 작성하여 사용 하는 것을 의미하며 이렇게 사용할 것을 권고

테스트 2.

  • 추가로 set 명령어는 lua 엔진을 사용할 뿐, used_memory_scripts 의 값이 변경 되는 내역은 없음
    • 기존 get 명령어나 return 하는 명령어의 경우 used_memory_scripts  값이 변경 되는 것을 확인할 수 있으나, 오로지 set 명령어의 경우 lua engine 의 값만 변경(used_memory_lua ) 되는 것을 확인 할  수 있다.
local src = KEYS[1]  
for i=1, src, 2 do  
	local test_key = 'lua_test_' .. i  
	redis.call('set', test_key, i)  
end;  
-> 한마디로 set lua_test_홀수번호 홀수번호  
EVAL "local src = KEYS[1] for i=1, src, 2 do local test_key = 'lua_test_' .. i redis.call('set', test_key, i) end;"
  1. 초기 값 확인
    1. used_memory_lua : 32768 / used_memory_scripts : 0 / number_of_cached_scripts : 0  
  2. lua 스크립트로 캐싱 진행
    1. used_memory_lua : 33792 / used_memory_scripts : 216 / number_of_cached_scripts : 1
    2. lua 엔진 및 메모리에 적재 된 것을 확인 (스크립트 등록 시 기본 동작 하는 것으로 확인)
  3. lua 스크립트 실행
    1. used_memory_lua : 63488 / used_memory_scripts : 216 / number_of_cached_scripts : 1
    2. lua 엔진은 사용하였지만, get 명령어 같이 조회 하거나 하는 것이 아니기 때문에 lua 메모리 쪽에 적재 되는 것은 없는 것으로 확인
  4. 다시 한번 lua 스크립트 실행
    1. 동일하게 lua 엔진은 사용하였지만, memory 는 사용 하지 않은 것을 확인
    2. 바로 lua 로 실행 하여도 동일하게  engine 은 사용하지만, memory는 변경 되지 않는 것을 확인 완료

결론

  • 동일한 의미로 보이는 Lua 스크립트라고 하더라도, 내용이 조금이라도 다르면 서로 다른 스크립트로 인식
  • 동일한 명령어 이라고 하더라도, return  의 유무에 따라 위의 의미와 같이 서로 다른 스크립트로 인식
  • set 명령어로만 이루어진 lua  스크립트는, 별도의 메모리를 사용하지 않음 (lua 엔진만 메모리 사용)
  • 그 외 메모리 사용률을 확인 하기 위해서는 used_memory_scripts  를 모니터링 하며, used_memory_lua 는 평소와 비슷한지 체크하면 좋을 듯 합니다.
  • Elasticache 를 이용한다면, Lua script 내용이 get 형태의 읽기로만 이루어진 내용이라면, read를 이용하는 것을 추천합니다.(Lua의 수행속도가 오래 걸린다면 write 뿐만 아니라 redis 자체가 싱글 스레드로 동작하기 때문에 대기를 하게 되지만, 적어도 read를 이용한다면 write에 대해서만큼은 영향을 덜 미치기 때문 / 하지만 Lua 성능 최적화는 꼭 합시다.)

그외

AWS 의 경우 Cloudwatch 상에서 Elasticache 지표에서는 used_momory_scripts / lua 등을 제공을 하지 않기 때문에 BytesUsedForCache 와 FreeableMemory 의 변화로 모니터링 하는 것으로 우회 하거나, 해당 지표를 직접 조회하여 모니터링 하는 것을 추천 드립니다.

 

참고

다양한 샘플을 참고 할 수 있음 : https://bstar36.tistory.com/348
https://redis.io/docs/manual/programmability/eval-intro/
AWS  Support 최원 님 도움 주셔서 감사합니다.

반응형
반응형

MongoDB 여러 메모리 지표 중 cursor를 발생하는 과정에서 spinlock 이 발생 시키지만 lock 으로는 잡히지 않는 내용을 보고 검색 중 tcmalloc 전체를 정리하는 시간을 가지게 되었습니다.


tcmalloc 이란 ?

  • 구글에서 만든 메모리 할당하는 라이브러리(memory allocation (malloc))
    • 메모리 풀을 사용하면
      • 빠른 메모리 할당
      • 메모리 단편화 감소
  • Thread Caching malloc (TCmalloc)
  • 메모리를 Thread Local Cache와 Central Heap으로 나누어서 관리
    • tcmalloc은 성능상의 이유로, 각각 스레드는 자체 로컬(Thread Local Cache) 여유 페이지 캐시와 중앙 여유 페이지(Central Heap) 캐시를 보유
    • 메모리를 신청할 때 Thread Local 여유 페이지 캐시(32k 이하) 에서 사용 가능한 메모리를  찾고==> 사용 가능한 메모리가 없을 때만 Central Heap 페이지캐시(4k page)에서 추가 할당 적용 (Thread Local Cache는 32K이하의 작은 오브젝트 들을 담당하며 메모리가 부족할 시에는 Central Heap에서 메모리를 얻어와서 할당. 그리고 32K가 넘어가는 큰 오브젝트들은 Central Heap에다 4K의 페이지 단위로 나누어서 메모리 맵을 이용하여 할당)
    • 단순 Central Heap은 일반적으로 사용하는 메모리 풀과 다를바가 없지만, Thread Local Cache가 있음으로 불필요한 동기화가 줄어들어 lock cost 가 꽤 많이 감소하여 성능향상 효과
    • THread 의 수가 늘어날 수록 메모리 단위가 작을 수록 TCMalloc 이 효율이 더 뛰어남
    • 출처: https://gamedevforever.com/31
 

Google Performance Tools - TCmalloc (Thread-Caching memory allocation)

안녕하세요.  라오그람이란 필명을 사용하는 김효진 입니다. 저는 서버 쪽 개발을 하고있구요, 원래는 게임 서버 개발자이지만 현재는 게임쪽이 아닌 잠시 다른 쪽 서버 분야를 개발하고 있습

gamedevforever.com

 

MongoDB tcmalloc

  • https://medium.com/daangn/memory-allocator-for-mongodb-1953f9cee06c (Memory Allocator for MongoDB - 당근마켓 팀블로그 Sunguck Lee 님)
  • C++로 개발되어 메모리 할당과 해제를 직접 처리하는 C 언어와는 달리, C++에서는 (일반적으로) Heap Memory의 할당과 해제가 매우 많이 발생
    • 별도의 Memory Allocator를 사용하지 않으면 리눅스 운영 체제의 기본 Memory Allocator인 PTMalloc2를 사용
    • MongoDB에서도 PTMalloc2보다는 다른 더 나은 TCMalloc을 코드 수준에서 내장
    • https://jira.mongodb.org/browse/SERVER-24268 (Investigate jemalloc as alternative to tcmalloc)
  • mongos는 메모리 설정 파라메터가 없으며, 전통적으로 많은 사용자들이 mongos는 많은 메모리를 사용하지 않으며 일반적인 경우 100~200MB 정도로 할당해도 충분하다고 알고 있음
  • MongoDB의 관리형 서비스인 Atlas MongoDB에서도 mongod(MongoDB 서버)와 mongos를 동일 인스턴스에 배포해서 서비스를 제공
  • mongos를 통해서 아주 큰 데이터를 읽어오는 경우, mongos는 일시적으로 많은 데이터를 버퍼링해야 하며 순간적으로 메모리 사용량이 증가
  • mongos는 적절한 페이징 사이즈만큼의 도큐먼트를 가져와서 클라이언트가 가져갈 때까지 버퍼링을 하기 때문에 1~2개의 클라이언트가 대량의 데이터를 읽어 간다고 해서 심각한 메모리 사용을 유발하지는 않음
  • MongoDB에서는 메모리를 해제할 때 메모리도 캐시로 반환되고 tcmalloc Background에서 OS로 천천히 반환
  • 기본적으로 tcmalloc은 최대 메모리(1GB, 1/8 * system_memory)까지 캐시하며, 이 값은 setParameter.tcmallocMaxTotalThreadCacheBytesParameter매개변수가 있지만 일반적으로 수정하지 않는 것이 좋음
  • WiredTiger cacheSizeGB를 올바르게 구성(약 60%)
  • Sort 의 경우 메모리 정렬에는 일반적으로 더 많은 Tempory Memory 가 필요
    • 그렇기 때문에 index를 생성할 때 seak - sort - range 순서로 index 생성하는 이유
  • primary 와 secondary 간의 replication의 간격이 너무 크면 안됨
    • secondary 가 oplog를 저장하고 가져오기 위해(테일러커서) buffer (default maxsize 256mb) 유지해야하는데, 백그라운드는 buffer에서 oplog를 검색하고 계속 적용해야하기 때문에 secondary의 동기화가 느리면 버퍼가 최대 메모리로 계속 사용하게 됨
  • colleaction 및 index의 수를 제어하여 메타 데이터의 메모리 오버헤드를 줄여야 함.
replSet:PRIMARY> db.serverStatus().tcmalloc
{
        "generic" : {
                "current_allocated_bytes" : NumberLong("55188352944"),
                "heap_size" : NumberLong("102460903424")
        },
        "tcmalloc" : {
                "pageheap_free_bytes" : NumberLong("11626672128"),
                "pageheap_unmapped_bytes" : NumberLong("31339495424"),
                "max_total_thread_cache_bytes" : NumberLong(1073741824),
                "current_total_thread_cache_bytes" : 207674832,
                "total_free_bytes" : NumberLong("4306382928"),
                "central_cache_free_bytes" : NumberLong("4098687488"),
                "transfer_cache_free_bytes" : 20608,
                "thread_cache_free_bytes" : 207674832,
                "aggressive_memory_decommit" : 0,
                "pageheap_committed_bytes" : NumberLong("71121408000"),
                "pageheap_scavenge_count" : 549140549,
                "pageheap_commit_count" : 614667087,
                "pageheap_total_commit_bytes" : NumberLong("119850820927488"),
                "pageheap_decommit_count" : 560377066,
                "pageheap_total_decommit_bytes" : NumberLong("119779699519488"),
                "pageheap_reserve_count" : 7546,
                "pageheap_total_reserve_bytes" : NumberLong("102460903424"),
                "spinlock_total_delay_ns" : NumberLong("1232934807643"),
                "release_rate" : 1,
                "formattedString" : "------------------------------------------------\nMALLOC:    55188353520 (52631.7 MiB) Bytes in use by application\nMALLOC: +  11626672128 (11088.1 MiB) Bytes in page heap freelist\nMALLOC: +  4098687488 ( 3908.8 MiB) Bytes in central cache freelist\nMALLOC: +        20608 (    0.0 MiB) Bytes in transfer cache freelist\nMALLOC: +    207674256 (  198.1 MiB) Bytes in thread cache freelists\nMALLOC: +    498335744 (  475.2 MiB) Bytes in malloc metadata\nMALLOC:  ------------\nMALLOC: =  71619743744 (68301.9 MiB) Actual memory used (physical + swap)\nMALLOC: +  31339495424 (29887.7 MiB) Bytes released to OS (aka unmapped)\nMALLOC:  ------------\nMALLOC: = 102959239168 (98189.6 MiB) Virtual address space used\nMALLOC:\nMALLOC:        5237759              Spans in use\nMALLOC:            182              Thread heaps in use\nMALLOC:          4096              Tcmalloc page size\n------------------------------------------------\nCall ReleaseFreeMemory() to release freelist memory to the OS (via madvise()).\nBytes released to the OS take up virtual address space but no physical memory.\n"
        }
}

replSet:SECONDARY> db.serverStatus().tcmalloc
{
        "generic" : {
                "current_allocated_bytes" : NumberLong("54850342264"),
                "heap_size" : NumberLong("95095918592")
        },
        "tcmalloc" : {
                "pageheap_free_bytes" : NumberLong("23660171264"),
                "pageheap_unmapped_bytes" : NumberLong("12539207680"),
                "max_total_thread_cache_bytes" : NumberLong(1073741824),
                "current_total_thread_cache_bytes" : 247460608,
                "total_free_bytes" : NumberLong("4046197384"),
                "central_cache_free_bytes" : NumberLong("3798717832"),
                "transfer_cache_free_bytes" : 18944,
                "thread_cache_free_bytes" : 247460608,
                "aggressive_memory_decommit" : 0,
                "pageheap_committed_bytes" : NumberLong("82556710912"),
                "pageheap_scavenge_count" : 20418440,
                "pageheap_commit_count" : 41285079,
                "pageheap_total_commit_bytes" : NumberLong("9607290798080"),
                "pageheap_decommit_count" : 27551593,
                "pageheap_total_decommit_bytes" : NumberLong("9524734087168"),
                "pageheap_reserve_count" : 27728,
                "pageheap_total_reserve_bytes" : NumberLong("95095918592"),
                "spinlock_total_delay_ns" : NumberLong("395391394174"),
                "release_rate" : 1,
                "formattedString" : "------------------------------------------------\nMALLOC:    54850342840 (52309.4 MiB) Bytes in use by application\nMALLOC: +  23660171264 (22564.1 MiB) Bytes in page heap freelist\nMALLOC: +  3798717832 ( 3622.7 MiB) Bytes in central cache freelist\nMALLOC: +        18944 (    0.0 MiB) Bytes in transfer cache freelist\nMALLOC: +    247460032 (  236.0 MiB) Bytes in thread cache freelists\nMALLOC: +    468451328 (  446.8 MiB) Bytes in malloc metadata\nMALLOC:  ------------\nMALLOC: =  83025162240 (79179.0 MiB) Actual memory used (physical + swap)\nMALLOC: +  12539207680 (11958.3 MiB) Bytes released to OS (aka unmapped)\nMALLOC:  ------------\nMALLOC: =  95564369920 (91137.3 MiB) Virtual address space used\nMALLOC:\nMALLOC:        5004341              Spans in use\nMALLOC:            181              Thread heaps in use\nMALLOC:          4096              Tcmalloc page size\n------------------------------------------------\nCall ReleaseFreeMemory() to release freelist memory to the OS (via madvise()).\nBytes released to the OS take up virtual address space but no physical memory.\n"
        }
}

지표들 내역

  • pageheap_free_bytes : 페이지 힙에 매핑된 사용 가능한 페이지 byte
    • 해당 영역은 요청 시 할당하여 사용 가능한 페이지
    • OS에 의해 swap이 발생하지 않는 상태라면, 항상 해당 가상 메모리 사용량으로 계산
  • total_free_bytes : central_cache_free_bytes + transfer_cache_free_bytes + thread_cache_free_bytes 로 구성
  • tcmalloc cache 사이즈를 확인하려면 pageheap_free_bytes 와 total_free_bytes 를 참조하면 가능
  • central_cache_free_bytes   : 클래스 size에 할당된 중앙 캐시 내의 free 바이트 수
    • 항상 가상 메모리 샤용량으로 계산되며, os에서 기본 메모리를 swap 하여 사용하지 않는 한 물리적 메모리 사용량으로도 계산
  • transfer_cache_free_bytes : 중앙 cache와 Thread Cache 간에 변환되기를 기다리는 free byte 수
    • 항상 가상 메모리 샤용량으로 계산되며, os에서 기본 메모리를 swap 하여 사용하지 않는 한 물리적 메모리 사용량으로도 계산
  • thread_cache_free_bytes : Thread Cache 내의 free byte 수
    • 항상 가상 메모리 샤용량으로 계산되며, os에서 기본 메모리를 swap 하여 사용하지 않는 한 물리적 메모리 사용량으로도 계산

 

MongoDB 에서 spinlock

  • collection 에 대한 작업을 하려고 할 때 해당 collection document에 lock 이 걸려 있으면, 지속적으로 앞에 있는 lock 이 만료되었는지 확인하는 작업(spin)
    • spinlock 값이 증가한다면, lock 이 길어지고 있다는 것을 의미하며, slow query 등을 확인하여 오랫동안 동작하는 쿼리 등을 확인
  • getmore 쿼리는 mongodb의 cursor 발생 하므로, spinlock 발생 시키지만, 이거는 DB log에서는 lock 으로 안 잡힘

 

spin lock 개념

  • Thread가 단순히 loop(spin) 돌면서 Lock을 소유하고 있는 Thread가 lock 반환될 때까지 계속 확인하며 기다리는 상태
  • Context Switching 으로 부하를 주기 보다는 잠시 기다리자는 컨셉으로 스위칭을 하지 않고 잠시 루프를 돌면서 재시도를 진행

그외 tcmalloc 관련 이슈

상황

 

[SERVER-37541] MongoDB Not Returning Free Space to OS - MongoDB Jira

 

jira.mongodb.org

 

주로 primary 만 사용하는데, 메모리가 해제되지 않는 이슈

해결방안

  • tcmallocRelease:1 를 실행하여 (release free) pageheap을 재활용
    • db.adminCommand({tcmallocRelease: 1})
    • 이 때 pageheap 전체를 lock 하기 때문에 온라인에서 사용할때는 주의 (사용량이 적을 때 사용)
  • 하지만 해당 명령어는 가급적 사용하지 않는 것이 좋음(문제라고 판단되기 전까지..)
    • 실제로는 메모리를 낭비하지 않고 해당 메모리를 이용하여 다른 곳에서도 사용할 수 있기 때문

tcmallocRelease:1 처리 후 메모리 해제된 내역

 

 


https://developer.aliyun.com/article/685044
https://jira.mongodb.org/browse/SERVER-37541
https://jira.mongodb.org/browse/SERVER-33296

  • current_allocated_byutes 가 8gb
    • 하지만 heap_size는 현재 14gb 에 이르고 있음 (swap 사용한 내용 포함 / mem-resident와 비슷)
    • pageheap_free_bytes의 누적으로 인한 것으로 예상
    • TCMALLOC_AGGRESSIVE_DECOMMIT 를 이용하여 해결(설정하게 되면 tcmalloc이 여유 페이지를 os로 적극적으로 반환하도록 하는 역할)
      • 하지만 부정적인 성능 영향이 있을것 같아 원인 해결이 필요해 보임
      • mongodb에서는 tcmalloc 이 해당 부정적인 영향보다 더 큰 이점(성능)이 있다고 하여 우선순위에서 밀려 미해결중
      • Mongo 4.4.10 에서도 발생하고 있다 함.
  • https://jira.mongodb.org/browse/SERVER-31417
 

Analysis of MongoDB tcmalloc memory cache

Keywords: Database MongoDB background From the perspective of monitoring, Secondary uses about 11GB more physical memory than Primary, For basic memory analysis, you can read this written by another student of the team first Troubleshooting documents, Th

programmer.group

 

반응형
반응형

MongoDB 를 Sharded cluster 로 구축 후 운영하면서 수정했던 파라메터 중 하나를 공유합니다.

TaskExecutorPool은 mongos 에서 설정하는 파라메터 값 중 하나입니다.
(해당 문서는 4.4 위주로 작성 되었습니다.)

 

TaskExecutorPool?

  • Real MongoDB(235page)
  • MongoDB 라우터(mongos)는 MongoDB 클라이언트로부터 요청되는 쿼리들을 처리하기 위해서 내부적으로 서버의 CPU 코어 개수만큼 TaskExecutorPool 를 준비
  • Thread Pool 과 동일한 개념으로 생각하면 이해가 쉬움
  • MongoDB Shard 노드(Member)와의 연결 정보를 가지는 connection pool를 하나씩 가지며, Connection pool은 내부적으로 sub-connectionpool를 보유
  • 샤드 서버당 하나씩 생성
  • 만약 2개의 샤드(노드)가 존재한다면, 하나의 샤드당 connnection pool은 2개씩의 sub-connectionpool를 보유 (소스 상 specific-pool 이라고 명칭)
  • taskExecutorPoolSize 조정의 예시
    • app과 같은 서버에서 mongos가 실행된다면, app에서 많은 연결 및 작업을 한다면 TaskExecutorPool의 개수를 수동으로 증가 시키는 것도 가능
    • CPU 코어가 많은 서버라면, connection 이 너무 과도하게 생성되어 오히려 mongo shard(node)에 부하가 발생한다고 판단되면, TaskExecutorPool 개수를 제한도 가능
  • 모니터링 시 해당 수치가 높게 나오면 Sharded Clsuter 에 문제가 있기 때문에 반드시 체크가 필요 합니다.

 

taskExecutorPoolSize
  • 주어진 mongos에 사용할 Task Executor Connection Pool 의 수
  • 사용 가능한 코어 수로 default 설정 (최소 4, 최대 64)
    • 4.2 에서는 Default 가 1이며, cpu core 수에서 해당 값 만큼 설정
    • 0 으로 설정 시 자동으로 설정
    • 4.0 이전에는 core 수가 4 이하면 4, core 수가 64 이상일 경우 64로 설정
  • open connection 수를 줄이려면 낮은 값으로 설정
    • 부하 발생 시 적절하게 대처하기 힘들 수 있음.
  • default 값이 적절하며, 코어 수가 많은 서버에서는 해당 옵션을 16 이하로 설정하는 것이 좋음
  • mongos는 multiple thread pool을 유지 가능
  • 코어 수당 최대 connection 는 ShardingTaskExecutorPoolMaxSize 만큼 설정 가능
    • ex > ShardingTaskExecutorPoolMaxSize : 100 으로 설정 하고, taskExecutorPoolSize 를 4로 설정 시 최대 400개의 connection 을 생성 및 연결

Task Executor Pool

sub-ConnectionPool (SpecificPool)
  • connection pool의 connection을 얼마나 보유할지 결정
  • ShardingTaskExecutorPool로 시작
  • value 값들은 모두 3.2.11 이후부터 설정가능

 

ShardingTaskExecutorPoolHostTimeoutMS

  • mongos 가 host 와 통신하지 않아 끊는 시간(Timeout)
  • Default 300000 (5 분)
  • 시간이 길수록 피크 발생 시 유연하게 대처가 가능.
  • 일반적으로 피크 기간?의 3~4배 시간으로 설정하는 것이 tip (피크-spike 치는 시간이 가령 5분동안 지속된다면, 해당 ShardingTaskExecutorPoolHostTimeoutMS을 15~20분 으로 설정하는 것을 추천)
    • Real MongoDB에서는 30분에서 1시간 정도를 추천

 

ShardingTaskExecutorPoolMaxSize

  • taskExecutor connection pool 이 mongod(sharded) 에 대해 connection 할 수 있는 최대 개수 ( 하나의 coonection pool 이 접속할 수 있는 최대 connection 수)
  • default 값이 무제한
  • 최대 connection 수는 ShardingTaskExecutorPoolMaxSize * taskExecutorPoolSize 로 계산
  • connection floods 가 발생하면 해당 값을 제한하여 설정하는 것이 유용
    • connection floods : TCP connection floods라고 하며, 공격자가 서버에 사용 가능한 TCP connection slot 을 고갈시키는 행위 (여기서는 사용 가능한 connection 이 없을 경우를 의미)


ShardingTaskExecutorPoolMinSize

  • 각 TaskExecutor connection pool 이 sharded node에 connection 할 수 있는 최소 수
  • default 1
  • cold start 시 대기 시간 문제가 있는 경우 해당 값 증가가 도움
  • 해당 값을 증가시키면, mongos 프로세스가 ShardingTaskExecutorPoolHostTimeoutMS 가 만료될때까지 open 된 상태 유지 (TaskExecutorPoolSize * PoolMinSize * mongos 개수 per shard)
    • Real MongoDB에서는 10개 정도의 값도 충분

 

ShardingTaskExecutorPoolRefreshRequirementMS

  • connection pool 안에서 connection heartbeat로 시도할 때 wait 최대 시간
  • Default 60000 (1 분)
  • default 값을 추천
  • 해당 값을 높이면 heartbeat 트래픽이 증가하여 idle load 가 증가
  • 해당 값을 낮추면 일시적인 네트워크 오류 수를 줄일 수 있음(connection timeout 으로 인한 오류 내역을 줄일 수 있음)

 

ShardingTaskExecutorPoolRefreshTimeoutMS

  • mongos가 heartbeat timeout 을 기다리는 최대 시간
  • Default 20000 (20 초)
  • 해당 값이 낮으면 mongos가 pool 안의 connection을 유지할 수 없음
  • 네트워크 대기 시간이 긴 경우 해당 값을 늘려 네트워크 연결 유지를 향상 가능
# 설정 방법 1 (mongos config 로 등록)
sharding:
  #configDB: config_replSet/10.28.195.139:27017,10.28.195.140:27017,10.28.195.141:27017
  configDB: config_replSet/10.6.98.32:27017,10.6.102.126:27017,10.6.98.62:27017
net:
  bindIp: 0.0.0.0
  port: 27019
processManagement:
  fork: true
  pidFilePath: "/data/mongos/mongos.pid"
security:
#  authorization: enabled
  keyFile: /usr/local/mongodb/mongo_repl.key
systemLog:
  destination: file
  path: "/data/mongos/log/mongos.log"
# logAppend: true


setParameter:
  taskExecutorPoolSize: 0
# 설정 방법 2 (명령어로)
mongos> db.runCommand({setParameter:1,taskExecutorPoolSize:0})
{
    "was" : 1,
"ok" : 1,
  "$clusterTime" : {
        "clusterTime" : Timestamp(1631672362, 1),
          "signature" : {
                    "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
            }
},
        "operationTime" : Timestamp(1631672362, 1)
}

#확인 방법
mongos> db.runCommand({getParameter:1,taskExecutorPoolSize:1})
{
    "taskExecutorPoolSize" : 0,
        "ok" : 1,
  "$clusterTime" : {
        "clusterTime" : Timestamp(1631672363, 1),
          "signature" : {
                    "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                "keyId" : NumberLong(0)
            }
},
        "operationTime" : Timestamp(1631672363, 1)
}

 

반응형

Connection pool 확인

  • TaskExecutorPool 개수를 확인 가능 (16개)
    • 내부에 각 Shard DB들로 추가 connection 확인 가능
mongos> db.runCommand({"connPoolStats":1})
{
        "numClientConnections" : 0,
        "numAScopedConnections" : 0,
        "totalInUse" : 1,
        "totalAvailable" : 180,
        "totalCreated" : 5871,
        "totalRefreshing" : 0,
        "replicaSetMatchingStrategy" : "matchPrimaryNode",
        "pools" : {
                "NetworkInterfaceTL-ShardRegistry" : {
                        "poolInUse" : 0,
                        "poolAvailable" : 3,
                        "poolCreated" : 41,
                        "poolRefreshing" : 0,
                        "192.168.0.126:27017" : {
                                "inUse" : 0,
                                "available" : 1,
                                "created" : 4,
                                "refreshing" : 0
                        },
                        "192.168.1.32:27017" : {
                                "inUse" : 0,
                                "available" : 1,
                                "created" : 35,
                                "refreshing" : 0
                        },
                        "192.168.1.62:27017" : {
                                "inUse" : 0,
                                "available" : 1,
                                "created" : 2,
                                "refreshing" : 0
                        }
                },
                "NetworkInterfaceTL-TaskExecutorPool-0" : {
                        "poolInUse" : 0,
                        "poolAvailable" : 9,
                        "poolCreated" : 355,
                        "poolRefreshing" : 0,
                        "192.168.0.101:27017" : {
                                "inUse" : 0,
                                "available" : 1,
                                "created" : 2,
                                "refreshing" : 0
                        },
                        "192.168.0.199:27017" : {
                        ...
                        
                   "NetworkInterfaceTL-TaskExecutorPool-1" : {
                        "poolInUse" : 1,
                        "poolAvailable" : 8,
                        "poolCreated" : 366,
                        "poolRefreshing" : 0,
                        "192.168.0.101:27017" : {
                                "inUse" : 0,
                                "available" : 1,
                                "created" : 5,
                                "refreshing" : 0
                        },
                        "192.168.0.199:27017" : {
                        ...
                  "NetworkInterfaceTL-TaskExecutorPool-10" : {
                        "poolInUse" : 0,
                        "poolAvailable" : 12,
                        "poolCreated" : 342,
                        "poolRefreshing" : 0,
                        "192.168.0.101:27017" : {
                                "inUse" : 0,
                                "available" : 1,
                                "created" : 2,
                                "refreshing" : 0
                        },
                        "192.168.0.199:27017" : {
                        ...
               "NetworkInterfaceTL-TaskExecutorPool-15" : {
                        "poolInUse" : 0,
                        "poolAvailable" : 10,
                        "poolCreated" : 349,
                        "poolRefreshing" : 0,
                        "192.168.0.101:27017" : {
                                "inUse" : 0,
                                "available" : 1,
                                "created" : 2,
                                "refreshing" : 0
                        },
                        "192.168.0.199:27017" : {
                                "inUse" : 0,
                                "available" : 1,
                                "created" : 1,
                                "refreshing" : 0
                        },
                        "192.168.0.92:27017" : {
                        ...

 

[참고]

Real MongoDB

Line Games 성세일님

AWS 이덕현님

https://www.mongodb.com/docs/v4.4/reference/parameters/#mongodb-parameter-param.taskExecutorPoolSize

https://muralidba.blogspot.com/2018/03/what-are-tunable-options-for-mongos.html

이미지 : https://www.modb.pro/db/52603

반응형
반응형

지난 블로그에서 Replica Set을 Archive 목적으로 StandAlone 으로 변경 후, 보안 이슈로 인해 Version Upgrade 도중 Local DB 관련하여 에러가 발생하여 Trouble Shooting 을 진행 하였습니다.

 

그래서 이번에는 Replica Set에서 StandAlone 으로 문제 없이 깨끗?하게 변경하는 부분에 대하여 테스트를 진행 하였습니다.

이번 테스트를 진행하면서 느낀점은, 몇몇 외국 블로그에 나온 내용들을 보면, 인증을 사용안하는 것일까 라는 의문이 생겼습니다. 왜냐하면 이번 테스트를 진행 하면서 인증(authorization) 로 인해 Local DB가 삭제가 되지 않는 이슈가 발생하였기 때문입니다.

 

글보다는 제가 진행한 방법에 대해서 이미지와 방법을 보시면 쉽게 변경 가능할 것 같습니다.

 

진행 방법

  1. Replica Set 멤버들 제거 (primary는 제거되지 않습니다. 물론 제거하는 방법도 존재-맨 하단 리플리케이션-멤버-재설정 참고)

  2. mongod.conf 에서 replication / security 모두 주석 처리 후 재 시작
  3. local DB 삭제 진행
  4. mongod.conf 에서 security 모두 원복 후 재 시작
  5. Local DB에서 startup_log collection 만 생성 되었는지 확인 및 방금 startup 로그만 존재하는 지도 확인
  6. 정상적으로 StandAlone DB 변경 완료
# 1. 멤버 삭제
# Primary 에서 진행되며, 각 멤버들만 삭제가 가능
# 기본형태 : rs.remove("host명:port")

replSet:PRIMARY> rs.remove("127.0.0.1:57018")
replSet:PRIMARY> rs.remove("127.0.0.1:57019")
----------------------------------------------------------------------------
# 2. config 수정 및 mongodb 재시작

$ vi /etc/mongod.conf

systemLog:
   destination: file
   path: /data/mongo_test/log/mongo.log
...
net:
   bindIp: 0.0.0.0
   port: 57017

#replication:
#   replSetName: "replSet"

#security:
#  authorization: enabled
#  keyFile: /data/mongo_test_repl.key


$ systemctl restart mongod.service
----------------------------------------------------------------------------
# 3. local DB 삭제 진행
$ mongo --port 57017
# 현재 standalone 으로 올라왔으며, security를 주석처리하였기 때문에 인증 없이 접속
> use local
> db.dropDatabase()

# 정상적으로 local DB가 삭제 된 것을 확인 가능
----------------------------------------------------------------------------
# 4. mongod.conf 에서 security 모두 원복 후 재시작

$ vi /etc/mongod.conf

systemLog:
   destination: file
   path: /data/mongo_test/log/mongo.log
...
net:
   bindIp: 0.0.0.0
   port: 57017

#replication:
#   replSetName: "replSet"

security:
  authorization: enabled
  keyFile: /data/mongo_test_repl.key
----------------------------------------------------------------------------
# 5. Local DB 확인 
$ mongo admin -uadmin -p --port 57017
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB
> 
> use local
switched to db local

> db.startup_log.find().pretty()

----------------------------------------------------------------------------
# 6. 완료

Replica Set 멤버 삭제

Replica Set member 들
Replica Set 멤버 제거

Stand Alone 형태의 단독 Mongodb 의 초기 모습

  • 단순 local 내에는 startup_log collection 만 존재하며, 해당 collection 에는 startup 에 대한 로그들이 존재

 

Authorization 상태에서 Local DB삭제 시 다음과 같은 에러 발생

  • 참고로, 4.2 부터는 writeConcern이 majority 라서 majority를 1로 주고 진행 하더라도 에러 발생하는 것을 확인 가능 (writeConcern의 문제가 아님)

그외

  • 일부 블로그에서는 각 collection 마다 삭제하는 것도 있었는데, 실제로 삭제가 되는 collection 이 있는가 하면, 반대로 동일하게 Auth 로 인해서 삭제가 되지 않는 collection  도 존재 하는 것을 확인

 


아래 내용은 replication 재설정 관련하여 도움을 받았던 블로그 입니다.

이 부분도 실제로 진행하였는데, 자료를 남기지 않아 추후 테스트하여 공유 하도록 하겠습니다.

출처: https://knight76.tistory.com/entry/mongodb-레플리케이션-멤버-재설정하기 [김용환 블로그(2004-2020):티스토리]

 

그 외 참고

https://9to5answer.com/how-to-convert-a-mongodb-replica-set-to-a-stand-alone-server

https://adelachao.medium.com/downgrade-mongodb-replica-set-to-a-standalone-node-fc50d58addf2

https://medium.com/@cjandsilvap/from-a-replica-set-to-a-standalone-mongodb-79fda2beaaaf

 

반응형
반응형

기존 Mongodb Upgrade 와 비슷한 문서이나, Replica set 에서 Archive 목적으로 StandAlone 으로 변경 후 Upgrade 진행 중 발생한 이슈에 대한 문서 입니다.

Replica Set using rpm upgrade (3.4 to 4.2)

 

[MongoDB] 3.4 to 4.2 upgrade (rpm)

RPM 으로 설치된 Replica Set 에 대해 Upgrade 방법 입니다. 기본적으로 Downtime 을 가지고 진행 합니다. Secondary 를 standalone 형태로 변경 후, 업그레이드 한다면 Downtime 없이 가능하며, 실제로 진행한 결..

hyunki1019.tistory.com

  • mongod.conf 에서 replica set 제거
  • 해당 상태에서 stand alone 형태로 startup 진행
  • Version Upgrade 진행

 

Repo 추가 및 설정

  • 하나의 yum Repository 로도 가능하나, 별도의 repository 추가하여 진행 하였습니다. (별다른 이유는 없습니다.)
  • 여기 까지는 위의 문서와 동일
cp /etc/yum.repos.d/mongodb-org-3.4.repo /etc/yum.repos.d/mongodb-org-3.6.repo 
$ cp /etc/yum.repos.d/mongodb-org-3.4.repo /etc/yum.repos.d/mongodb-org-4.0.repo 
$ cp /etc/yum.repos.d/mongodb-org-3.4.repo /etc/yum.repos.d/mongodb-org-4.2.repo
# 3.6 추가
$ vi /etc/yum.repos.d/mongodb-org-3.6.repo 

[mongodb-org-3.6] 
name=MongoDB Repository 
baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/3.6/x86_64/ 
gpgcheck=1 
enabled=1 
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

# 4.0 추가
$ vi /etc/yum.repos.d/mongodb-org-4.0.repo 

[mongodb-org-4.0] 
name=MongoDB Repository 
baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/4.0/x86_64/ 
gpgcheck=1 
enabled=1 
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc

# 4.2 추가
$ vi /etc/yum.repos.d/mongodb-org-4.2.repo 

[mongodb-org-4.2] 
name=MongoDB Repository 
baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/4.2/x86_64/ 
gpgcheck=1 
enabled=1 
gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc

# yum 초기화 진행
$ yum clean all 
$ yum update list

 

MongoDB Replica Set to Standalone 

  • 단순히 conf 파일에서 replication 관련 항목을 주석 후 진행 (<- 원인)
$ vi /etc/mongod.conf 
# 아래 replication 내역 주석 처리
...
#replication:
#   replSetName: "replSet"
...

$ systemctl stop mongod.service

 

MongoDB 3.4 to 4.2 Upgrade 진행

  • 해당 문서를 보면서 upgrade 를 진행 한다면 4.0 까지만 upgrade 진행 후 아래 모든 내용의 글을 읽으신 후에 4.2 로 진행 하시기 바랍니다.!!!!!
############ 3.6 ############
# mongo 서버 종료
$ systemctl stop mongod.service

# yum 으로 update 진행
$ yum -y update mongodb-org-3.6.23

# mongodb 서버 시작
$ systemctl start mongod.service

# mongodb 접속 후 확인
$ mongo admin -uadmin -p

# 현재값 확인
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

# 중요!!!# featureCompatibilityVersion 수정
> db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } )

# 정상적으로 변경되었는지 확인
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

############ 4.0 ############
# mongo 서버 종료
$ systemctl stop mongod.service

# yum 으로 update 진행
$ yum -y update mongodb-org-4.0.27

# mongodb 서버 시작
$ systemctl start mongod.service

# mongodb 접속 후 확인
$ mongo admin -uadmin -p

# 현재값 확인
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

# 중요!!!# featureCompatibilityVersion 수정
> db.adminCommand( { setFeatureCompatibilityVersion: "4.0" } )

# 정상적으로 변경되었는지 확인
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

############ 4.2 ############
# mongo 서버 종료
$ systemctl stop mongod.service

# yum 으로 update 진행
$ yum -y update mongodb-org-4.2.18

# mongodb 서버 시작
$ systemctl start mongod.service
############################### 에러 발생하면서 startup 이 안되는 이슈 발생

 

발생 이슈

  • 전제 : 기존 Replica Set에서 StandAlone 형태로 변경 후 버전 업그레이드 진행
    • cf) Replica set 에서 업그레이드 진행시 다음과 같은 문제는 발생하지 않음
  • 문제 : 4.0 에서 4.2로 업그레이드 진행 후 startup 진행 시 startup 이 되지 않는 이슈
  • 에러 내역 (로그)
    • 주요 에러 내역
      • shutting down with code:100
      • exception in initAndListen: Location40415: BSON field 'MinValidDocument.oplogDeleteFromPoint' is an unknown field., terminating
$ systemctl start mongod.service
-> error 발생하면서 startup 이 되지 않음

mongod.log

2022-07-01T17:02:59.368+0900 I  CONTROL  [main] ***** SERVER RESTARTED *****
2022-07-01T17:02:59.370+0900 I  CONTROL  [main] Automatically disabling TLS 1.0, to force-enable TLS 1.0 specify --sslDisabledProtocols 'none'
2022-07-01T17:02:59.373+0900 W  ASIO     [main] No TransportLayer configured during NetworkInterface startup
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten] MongoDB starting : pid=36325 port=27017 dbpath=/data/mongo/repl_0 64-bit host=192.168.0.1
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten] db version v4.2.21
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten] git version: b0aeed9445ff41af57e1f231bce990b3
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten] OpenSSL version: OpenSSL 1.0.2k-fips  26 Jan 2017
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten] allocator: tcmalloc
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten] modules: none
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten] build environment:
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten]     distmod: amazon2
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten]     distarch: x86_64
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten]     target_arch: x86_64
2022-07-01T17:02:59.373+0900 I  CONTROL  [initandlisten] options: { config: "/etc/mongod.conf", net: { bindIp: "0.0.0.0", port: 27017 }, processManagement: { fork: true, pidFilePath: "/var/run/mongodb/mongod.pid" }, security: { authorization: "enabled" }, storage: { dbPath: "/data/mongo/repl_0", journal: { enabled: true } }, systemLog: { destination: "file", logAppend: true, path: "/var/log/mongodb/mongod.log", quiet: true } }
2022-07-01T17:02:59.373+0900 I  STORAGE  [initandlisten] Detected data files in /data/mongo/repl_0 created by the 'wiredTiger' storage engine, so setting the active storage engine to 'wiredTiger'.
2022-07-01T17:02:59.373+0900 I  STORAGE  [initandlisten] wiredtiger_open config: create,cache_size=7360M,cache_overflow=(file_max=0M),session_max=33000,eviction=(threads_min=4,threads_max=4),config_base=false,statistics=(fast),log=(enabled=true,archive=true,path=journal,compressor=snappy),file_manager=(close_idle_time=100000,close_scan_interval=10,close_handle_minimum=250),statistics_log=(wait=0),verbose=[recovery_progress,checkpoint_progress],
2022-07-01T17:02:59.914+0900 I  STORAGE  [initandlisten] WiredTiger message [1656662579:914502][36325:0x7ff6d143a080], txn-recover: Recovering log 71644 through 71645
2022-07-01T17:02:59.985+0900 I  STORAGE  [initandlisten] WiredTiger message [1656662579:985670][36325:0x7ff6d143a080], txn-recover: Recovering log 71645 through 71645
...
2022-07-01T17:03:00.247+0900 I  STORAGE  [initandlisten] WiredTiger message [1656662580:247926][36325:0x7ff6d143a080], txn-recover: Set global recovery timestamp: (0, 0)
2022-07-01T17:03:00.258+0900 I  RECOVERY [initandlisten] WiredTiger recoveryTimestamp. Ts: Timestamp(0, 0)
2022-07-01T17:03:00.260+0900 I  STORAGE  [initandlisten] No table logging settings modifications are required for existing WiredTiger tables. Logging enabled? 1
2022-07-01T17:03:00.267+0900 I  STORAGE  [initandlisten] Starting OplogTruncaterThread local.oplog.rs
2022-07-01T17:03:00.267+0900 I  STORAGE  [initandlisten] The size storer reports that the oplog contains 44774827 records totaling to 53269933556 bytes
2022-07-01T17:03:00.267+0900 I  STORAGE  [initandlisten] Sampling the oplog to determine where to place markers for truncation
2022-07-01T17:03:00.269+0900 I  STORAGE  [initandlisten] Sampling from the oplog between Jun 12 09:53:56:57 and Jun 30 10:45:36:1 to determine where to place markers for truncation
2022-07-01T17:03:00.269+0900 I  STORAGE  [initandlisten] Taking 992 samples and assuming that each section of oplog contains approximately 451255 records totaling to 536871395 bytes
2022-07-01T17:03:00.743+0900 I  STORAGE  [initandlisten] Placing a marker at optime Jun 12 13:10:49:4
2022-07-01T17:03:00.743+0900 I  STORAGE  [initandlisten] Placing a marker at optime Jun 12 17:58:42:4
....
2022-07-01T17:03:00.743+0900 I  STORAGE  [initandlisten] Placing a marker at optime Jun 30 08:04:48:175
2022-07-01T17:03:00.743+0900 I  STORAGE  [initandlisten] WiredTiger record store oplog processing took 475ms
2022-07-01T17:03:00.744+0900 I  STORAGE  [initandlisten] Timestamp monitor starting
2022-07-01T17:03:00.771+0900 I  STORAGE  [initandlisten] exception in initAndListen: Location40415: BSON field 'MinValidDocument.oplogDeleteFromPoint' is an unknown field., terminating
2022-07-01T17:03:00.771+0900 I  REPL     [initandlisten] Stepping down the ReplicationCoordinator for shutdown, waitTime: 10000ms
2022-07-01T17:03:00.771+0900 I  SHARDING [initandlisten] Shutting down the WaitForMajorityService
2022-07-01T17:03:00.771+0900 I  NETWORK  [initandlisten] shutdown: going to close listening sockets...
2022-07-01T17:03:00.771+0900 I  NETWORK  [initandlisten] Shutting down the global connection pool
2022-07-01T17:03:00.771+0900 I  STORAGE  [initandlisten] Shutting down the FlowControlTicketholder
2022-07-01T17:03:00.771+0900 I  -        [initandlisten] Stopping further Flow Control ticket acquisitions.
2022-07-01T17:03:00.771+0900 I  STORAGE  [initandlisten] Shutting down the PeriodicThreadToAbortExpiredTransactions
2022-07-01T17:03:00.771+0900 I  STORAGE  [initandlisten] Shutting down the PeriodicThreadToDecreaseSnapshotHistoryIfNotNeeded
2022-07-01T17:03:00.771+0900 I  REPL     [initandlisten] Shutting down the ReplicationCoordinator
2022-07-01T17:03:00.771+0900 I  SHARDING [initandlisten] Shutting down the ShardingInitializationMongoD
2022-07-01T17:03:00.771+0900 I  REPL     [initandlisten] Enqueuing the ReplicationStateTransitionLock for shutdown
2022-07-01T17:03:00.771+0900 I  -        [initandlisten] Killing all operations for shutdown
...
2022-07-01T17:03:01.196+0900 I  STORAGE  [initandlisten] WiredTiger message [1656662581:196670][36325:0x7ff6d143a080], txn-recover: Set global recovery timestamp: (0, 0)
2022-07-01T17:03:01.335+0900 I  STORAGE  [initandlisten] shutdown: removing fs lock...
2022-07-01T17:03:01.335+0900 I  -        [initandlisten] Dropping the scope cache for shutdown
2022-07-01T17:03:01.335+0900 I  CONTROL  [initandlisten] now exiting
2022-07-01T17:03:01.335+0900 I  CONTROL  [initandlisten] shutting down with code:100

 

해결 방안

  • 4.0 Downgrade 진행 및 local DB의 replset.minvalid 컬렉션의 oplogDeleteFromPoint 필드 unset 진행
# 4.0 Downgrade 진행
$ yum -y downgrade mongodb-org-4.0.27

# mongodb startup 진행
$ systemctl start mongod.service

# mongodb 접속 후 확인
$ mongo admin -uadmin -p

# local 에서 replset.minvalid Collection 의 oplogDeleteFromPoint 필드 $unset 진행
> use local
switched to db local

> db.replset.minvalid.find({}).pretty ();
{
        "_id" : ObjectId("5ec3b7c56db7b066b3f5d5e3"),
        "ts" : Timestamp(1643225280, 1),
        "t" : NumberLong(7),
        "oplogDeleteFromPoint" : Timestamp(0, 0)
}

# update 진행 검색 조건은 _id 결과로 $unset 진행
> db.replset.minvalid.update(
...  { "_id" : ObjectId("5ec3b7c56db7b066b3f5d5e3")},
...    { $unset: { oplogDeleteFromPoint: ""} }
... );
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

# 해당 필드 값 확인
> db.replset.minvalid.find({}).pretty ();
{
        "_id" : ObjectId("5ec3b7c56db7b066b3f5d5e3"),
        "ts" : Timestamp(1643225280, 1),
        "t" : NumberLong(7)
}
> exit

# 이후 다시 mongodb 4.2 upgrade 진행
# mongo 서버 종료
$systemctl stop mongod.service

# yum 으로 update 진행
yum -y update mongodb-org-4.2.18

# mongodb 서버 시작
$ systemctl start mongod.service

# mongodb 접속 후 확인
$ mongo admin -uadmin -p

# 현재값 확인
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

# 중요!!!# featureCompatibilityVersion 수정
> db.adminCommand( { setFeatureCompatibilityVersion: "4.2" } )

# 정상적으로 변경되었는지 확인
> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

 

발생 원인

  • Replica set 을 정상적으로 삭제 하지 않고 단순 config 파일에서 수정 후 진행하다가 발생한 이유
  • mongodb 4.2에서 MinValidDocument.oplogDeleteFromPoint dependency (예상)

 

발생 방지 방법

  • MongoDB Replica set 에서 StandAlone 으로 변경 시 정상적인 방법으로 진행
# 1. 모든 Secondary 삭제 진행
repl_set:PRIMARY> rs.remove("Secondary 호스트 이름:27017")
repl_set:PRIMARY> rs.remove("Arbiter 호스트 이름:27018")

# 2. config 파일에서 replication 주석 처리 또는 제거
$ vi /etc/mongod.conf
...
#replication:
#   replSetName: "replSet"
...

# 3. mongodb 재시작(Primary)
$ systemctl restart mongod.service

# 4. local database 삭제
# mongodb 접속 시 현재 standalone 상태
> use local
> db.dropDatabase()

# 5. mongodb 깔끔하게 확인차 재시작(Primary)
$ systemctl restart mongod.service

 

결론

  • Replica Set의 동작 방식 뿐만 아니라 각 DB(Local, admin 등)들의 역할에 대해서 다시 한번 공부가 필요
  • MongoDB에 대한 공부 공부 공부!!!

 

해당 문제를 해결하는 과정에 많은 도움을 주신 TechPM 박경배 팀장님에게 감사 인사 드립니다.

반응형
반응형
  • RPM 으로 설치된 Replica Set 에 대해 Upgrade 방법 입니다.
  • 기본적으로 Downtime 을 가지고 진행 합니다.
    • Secondary 를 standalone 형태로 변경 후, 업그레이드 한다면 Downtime 없이 가능하며, 실제로 진행한 결과 문제 없이 업그레이드 진행 하였습니다. 
    • 이 부분에 대해서는 별도로 문서는 만들지 않았습니다. 
  • PSA 구조로 진행하였으며, PSS 구조로 진행 한다면 Arbiter 업그레이드 대신 Secondary 진행한 그대로 대신 진행 하면 됩니다.
  • MongoDB 3.4 to 4.2 로 진행 합니다.
  • aws ec2 - amazon2 에서 진행 하였습니다.

 

Repo 추가 및 설정

  • 하나의 yum Repository 로도 가능하나, 별도의 repository 추가하여 진행 하였습니다. (별다른 이유는 없습니다.)
cp /etc/yum.repos.d/mongodb-org-3.4.repo /etc/yum.repos.d/mongodb-org-3.6.repo 
$ cp /etc/yum.repos.d/mongodb-org-3.4.repo /etc/yum.repos.d/mongodb-org-4.0.repo 
$ cp /etc/yum.repos.d/mongodb-org-3.4.repo /etc/yum.repos.d/mongodb-org-4.2.repo
# 3.6 추가
$ vi /etc/yum.repos.d/mongodb-org-3.6.repo 

[mongodb-org-3.6] 
name=MongoDB Repository 
baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/3.6/x86_64/ 
gpgcheck=1 
enabled=1 
gpgkey=https://www.mongodb.org/static/pgp/server-3.6.asc

# 4.0 추가
$ vi /etc/yum.repos.d/mongodb-org-4.0.repo 

[mongodb-org-4.0] 
name=MongoDB Repository 
baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/4.0/x86_64/ 
gpgcheck=1 
enabled=1 
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc

# 4.2 추가
$ vi /etc/yum.repos.d/mongodb-org-4.2.repo 

[mongodb-org-4.2] 
name=MongoDB Repository 
baseurl=https://repo.mongodb.org/yum/amazon/2/mongodb-org/4.2/x86_64/ 
gpgcheck=1 
enabled=1 
gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc

# yum 초기화 진행
$ yum clean all 
$ yum update list

 

MongoDB 3.6 Upgrade 진행

  • Secondary -> Arbiter -> Primary 순으로 진행 합니다.
############ Secondary ############
# mongo 서버 종료 
$ systemctl stop mongod.service 

# yum 으로 update 진행 
$ yum update mongodb-org-3.6.23 

# mongodb 서버 시작 
$ systemctl start mongod.service 

# mongodb 접속 후 확인 
$ mongo admin -uadmin -p 

# replica 접속 되었는지 확인 
repl_set:SECONDARY> rs.status()

############ Arbiter ############
# mongo 서버 종료 
$ systemctl stop mongod_arb.service 

# yum 으로 update 진행 
$ yum update mongodb-org-3.6.23 

# mongodb 서버 시작 
$ systemctl start mongod_arb.service 

# mongodb 접속 후 확인 
$ mongo --port 27018 

# replica 접속 되었는지 확인 
repl_set:ARBITER> rs.status()

############ Primary ############
# mongo 서버 종료 
$ systemctl stop mongod.service 

# yum 으로 update 진행 
$ yum update mongodb-org-3.6.23 

# mongodb 서버 시작 
$ systemctl start mongod.service 

# mongodb 접속 후 확인 
$ mongo admin -uadmin -p 
# replica 접속 되었는지 확인 
repl_set:PRIMARY> rs.status() 

############ 중요!!! ############
# featureCompatibilityVersion 수정 
repl_set:PRIMARY> db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } ) 
# 정상적으로 변경되었는지 확인 
repl_set:PRIMARY> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

 

 

MongoDB 4.0 Upgrade 진행

  • Secondary -> Arbiter -> Primary 순으로 진행 합니다.
############ Secondary ############
# mongo 서버 종료 
$ systemctl stop mongod.service 

# yum 으로 update 진행 
$ yum update mongodb-org-4.0.27 

# mongodb 서버 시작 
$ systemctl start mongod.service 

# mongodb 접속 후 확인 
$ mongo admin -uadmin -p 

# replica 접속 되었는지 확인 
repl_set:SECONDARY> rs.status()

############ Arbiter ############
# mongo 서버 종료 
$ systemctl stop mongod_arb.service 

# yum 으로 update 진행 
$ yum update mongodb-org-4.0.27 

# mongodb 서버 시작 
$ systemctl start mongod_arb.service 

# mongodb 접속 후 확인 
$ mongo --port 27018 

# replica 접속 되었는지 확인 
repl_set:ARBITER> rs.status()

############ Primary ############
# mongo 서버 종료 
$ systemctl stop mongod.service 

# yum 으로 update 진행 
$ yum update mongodb-org-4.0.27 

# mongodb 서버 시작 
$ systemctl start mongod.service 

# mongodb 접속 후 확인 
$ mongo admin -uadmin -p 
# replica 접속 되었는지 확인 
repl_set:PRIMARY> rs.status() 

############ 중요!!! ############
# featureCompatibilityVersion 수정 
repl_set:PRIMARY> db.adminCommand( { setFeatureCompatibilityVersion: "4.0" } ) 
# 정상적으로 변경되었는지 확인 
repl_set:PRIMARY> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

 

MongoDB 4.2 Upgrade 진행

  • Secondary -> Arbiter -> Primary 순으로 진행 합니다.
############ Secondary ############
# mongo 서버 종료 
$ systemctl stop mongod.service 

# yum 으로 update 진행 
$ yum update mongodb-org-4.2.18

# mongodb 서버 시작 
$ systemctl start mongod.service 

# mongodb 접속 후 확인 
$ mongo admin -uadmin -p 

# replica 접속 되었는지 확인 
repl_set:SECONDARY> rs.status()

############ Arbiter ############
# mongo 서버 종료 
$ systemctl stop mongod_arb.service 

# yum 으로 update 진행 
$ yum update mongodb-org-4.2.18

# mongodb 서버 시작 
$ systemctl start mongod_arb.service 

# mongodb 접속 후 확인 
$ mongo --port 27018 

# replica 접속 되었는지 확인 
repl_set:ARBITER> rs.status()

############ Primary ############
# mongo 서버 종료 
$ systemctl stop mongod.service 

# yum 으로 update 진행 
$ yum update mongodb-org-4.2.18

# mongodb 서버 시작 
$ systemctl start mongod.service 

# mongodb 접속 후 확인 
$ mongo admin -uadmin -p 
# replica 접속 되었는지 확인 
repl_set:PRIMARY> rs.status() 

############ 중요!!! ############
# featureCompatibilityVersion 수정 
repl_set:PRIMARY> db.adminCommand( { setFeatureCompatibilityVersion: "4.2" } ) 
# 정상적으로 변경되었는지 확인 
repl_set:PRIMARY> db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

 

  • 반복 작업이지만, MongoDB는 순차적으로 upgrade 하는 것이 권고 사항 입니다.
  • 또한, featureCompatibilityVersion 을 수정하지 않는 경우 다음 version upgrade 이후 startup 이 되지 않는 이슈가 발생 합니다.
  • 이 때, 이전 version으로 downgrade 이 후, featureCompatibilityVersion 수정 후 다시 업그레이드를 하게 되면 진행이 가능합니다.
    • 모든 upgrade 작업은 백업은 필수! 입니다.
    • 가령, 문제가 발생하여 repair 명령어를 이용하여 startup 을 하게 되면, 모든 collection repair 및 index rebuild 까지 진행 하기 때문에 데이터 size 가 작은 사이트에서는 크게 이슈가 발생하지 않겠지만, 저희처럼 테라바이트 단위라면 repair 시간을 예측 하기 힘든 상황이 발생 합니다. (6테라 size의 db를 repair 로 만 하루 넘어가도 끝나지 않아 포기하고 기존 ec2 snapshot 으로 복구 진행 하였습니다.)
  • 이후, 다른 글에서 upgrade 과정에서 MinValidDocument.oplogDeleteFromPoint is an unknown field 이슈에 대해 해결 방법을 공유 하도록 하겠습니다.
반응형
반응형
  1. 개요 및 아키텍처
    1. 개요
      1. 메모리 DB (높은 처리량 - Replication 읽기 및 쓰기, 대기 시간 등 높은 처리 가능)
      2. 레디스와 호환이 되며, 레디스 관련한 것들을 모두 사용 가능 (v6.2)
      3. Multi-AZ 를 지원하여 빠르게 failover 및 복구, 재시작이 가능
    2. 특징
      1. Primary / Replica 간의 강력한 일관성 보장
      2. ms 단위의 읽기,쓰기 지연시간 (클러스터당 최대 1억6천만 tps)
      3. redis 호환
      4. 빠른 데이터 복구 및 재시작 제공 (multi-az, transaction log )
      5. multi-az를 통한 자동 페일오버 및 노드 fail에 대한 감지 및  복구
      6. replication 및 shard를 이용한 노드 추가, scale out, scale up-down 가능
      7. primary 에 대한 read/write 일관성 보장 및 복제 노드에 대한 일관성 보장 가능(read / write concern으로 예상)
      8. 사용자 인증 및 네트워크 인증, 암호화 기능 제공
      9. s3로 자동 스냅샷 (최대 35일 - rds 와 동일)
      10. 하나의 클러스터로 최대 500개 노드 및 100tb 이상의 storage 지원(레플리카 포함)
      11. AWS KMS keys를 사용한 TLS 암호화(8번과 동일)
      12. Redis를 통한 사용자 인증 및 권한 부여(ACL)(8번과 동일)
      13. AWS Graviton2 인스턴스 유형 지원
      14. VPC, Cloudwatch, CloudTrail, AWS SNS 서비스와의 통합
      15. 완전 관리형 소프트웨어 패치 및 업그레이드 지원
      16. 관리 API를 위한 AWS IAM(Identity and Access Management) 통합 및 태그 기반 액세스 제어
    3. 주요 기능
      1. Cluster
        1. MemoryDB 서비스를 운영하는 하나 이상의 노드 모음 (서비스의 개념)
        2. Shard는 Memory DB Set 단위들의 모임으로 Cluster 내에 존재
          1. Noes ⊂ Shard ⊂ Cluster  = 서비스 DB
        3. Memory DB Set 에는 하나의 Primary 와 최대 5개의 Replica 노드들을 보유 가능
        4. Primary 는 read/write 가능하며, Replica node들은 only read 만 처리
        5. Primary 장애 시 replica node들 중 하나를 primary 로 승격
        6. cluster 생성 시 redis 버전을 지정
        7. cluster 내 Memory DB 기능
          1. cluster 추가
          2. cluster 수정
          3. cluster 스냅샷 가져오기
          4. cluster 삭제
          5. cluster 내 요소 보기
          6. cluster 에 비용 할당 태그 추가 / 삭제
      2. Nodes
        1. MemoryDB 구성 중 가장 작은 단위 (EC2 기반)
        2. 클러스터에 속하며, cluster 생성 시 정해진 버전의 엔진 기반
        3. 필요한 경우 클러스터의 노드를 다른 유형으로 up / down 가능
        4. 단독으로 up / down 가능은 체크 필요
      3. Shards
        1. 하나의 샤드에는 1~6개의 노드로 구성되며, primary 1개에 5개의 replica 로 구성
        2. MemoryDB Cluster는 항상 적어도 하나의 샤드로 구성
        3. 클러스터 내 최대 500개의 샤드를 생성 가능
          1. 최대 500개 노드를 가질 수 있으므로, 1샤드=1 Primary 노드로 하는 경우 500샤드 구성 가능
          2. 단, IP주소가 충분한지 체크 필요
      4. Parameter groups
        1. parameter group 을 적용함으로써 각기 다른 parameter 를 적용 가능
        2. RDS 와 동일 개념
      5. Subnet Groups
        1. VPC 내 subnet group 으로 구성
      6. Access Control Lists
        1. Redis ACL 규칙을 적용 가능 (Access Control List)
      7. Users
        1. 이름과 암호를 가진 User를 생성하여 접속 가능

        2. 2. 사용자는 ACL 구성원
  2. Redis vs Elasticache Redis vs MemoryDB for Redis
    1. 성능 : Elasticache 가 Memory DB 보다 쓰기 읽기 성능이 더 좋음
  Redis ElastiCache for Redis MemoryDB for Redis
내구성 AOF, RDB 로 내구성 처리
(AOF 파일에 쓰기 전 장애 시 데이터 손실 발생 가능성)
Primary 리턴 응답이라, Replica node에 데이터 적재 전 장애 시 손실 발생 가능성 존재
Redis 데이터구조 및 API
내구성이 뛰어난 Inmemory DB (장애 시 무손실 복구)
(Transaction log 까지 작성 후 응답이기 때문에 무손실 가능)
Redis 데이터구조 및 API
성능 12만/sec read/write : μs (마이크로초) read : μs (마이크로초)
write : ms (한자리 Millisecond)
Cluster mode Cluster mode 활성화 비활성화 모두 가능 cluster mode 활성화, 비활성화 모두 가능 cluster mode 활성화 필수
접속 redis-cli 로 접속
백업
  • 조건부 RDB 백업 가능
  • AOF 로 모든 DML 쿼리 저장
  • 24시간 동안 20개까지 스냅샷 생성 제한
    • cluster mode에서만 백업
  • 해당 Region에서 수동 스냅샷 보유 개수 제한은 없음
  • 24시간 동안 20개까지 스냅샷 생성 제한
    • cluster mode에서만 백업
  • 해당 Region에서 수동 스냅샷 보유 개수 제한은 없음
복원
  • RDB 시점 복원 가능
  • AOF 이용하여 원하는 명령문까지 복원 가능
  • RDB 스냅샷 복원
  • 별도의 Replica node가 없을 경우 유실(마지막 스냅샷 이후 부터 유실)
  • RDB 스냅샷 복원
  • 특정시점복원은 불가 (Point in  time Recovery 불가)
  • Transaction log를 이용하여 장애 최종 복원 가능
고가용성 replica
shard 구성
Replica
Shard 구성
 
replica node의 복제가 실패하는 경우
  • 실패 노드를 감지하여 오프라인 전환 및 동일한 AZ에 교체노드를 실행하여 동기화 진행
MemoryDB Multi-AZ primary 장애
  • MemoryDB에서 Primary 오류 감지하면, replica node들 중 primary 정합성체크 후 primary 승격 후 다른 AZ에 있는 primary를 spin up 이후 동기화 진행
    (다른 AZ의 primary 를 spin up 이후 동기화 하는 것보다 더 빠름)
복제 replica 구성
  • async 복제
    • rdb로 먼저 전체 복제
    • 복제 버퍼 내용 복제
replica 구성
  • async 복제
    • rdb 전체 복제
    • (Reserved Memory) 내용 복제
transaction log를 사용하는 async 복제
  • transaction log에 저장(영구저장)하므로 데이터 손실될 위험이 없음
  • Multi-AZ 강력히 권장
  1. 가격 및 Region
    1. 가격
      1. https://aws.amazon.com/ko/memorydb/pricing/ 참고
      2. Elastic Cache 보다 하루 1달러 더 비싸다고 공유 받음
    2. 지원 region
      1. 현재 지원하고 있는 내역 리스트
      2. US East (N. Virginia), US East (Ohio), US West (Oregon), US West (Northern California), EU (Ireland), EU (London), EU (Stockholm), Asia Pacific (Mumbai), Asia Pacific (Seoul), Asia Pacific (Singapore), Asia Pacific (Sydney), Asia Pacific (Tokyo),  Canada (Central), and South America (Sao Paulo)  - 21년10월 정보

 

참고

https://docs.aws.amazon.com/memorydb/latest/devguide/what-is-memorydb-for-redis.html
https://docs.aws.amazon.com/memorydb/latest/devguide/components.html

Elasticache vs MemoryDB 성능 : https://www.sentiatechblog.com/benchmark-series-amazon-memorydb-and-how-it-stands-compared-to-amazon
https://youtu.be/Jbq_XZMZEKY

반응형
반응형
  1. 개요 및 아키텍처
    1. 개요
      1. 메모리 DB (높은 처리량 - Replication 읽기 및 쓰기, 대기 시간 등 높은 처리 가능)
      2. 레디스와 호환이 되며, 레디스 관련한 것들을 모두 사용 가능 (v6.2)
      3. Multi-AZ 를 지원하여 빠르게 failover 및 복구, 재시작이 가능
    2. 특징
      1. Primary / Replica 간의 강력한 일관성 보장
      2. ms 단위의 읽기,쓰기 지연시간 (클러스터당 최대 1억6천만 tps)
      3. redis 호환
      4. 빠른 데이터 복구 및 재시작 제공 (multi-az, transaction log )
      5. multi-az를 통한 자동 페일오버 및 노드 fail에 대한 감지 및  복구
      6. replication 및 shard를 이용한 노드 추가, scale out, scale up-down 가능
      7. primary 에 대한 read/write 일관성 보장 및 복제 노드에 대한 일관성 보장 가능(read / write concern으로 예상)
      8. 사용자 인증 및 네트워크 인증, 암호화 기능 제공
      9. s3로 자동 스냅샷 (최대 35일 - rds 와 동일)
      10. 하나의 클러스터로 최대 500개 노드 및 100tb 이상의 storage 지원(레플리카 포함)
      11. AWS KMS keys를 사용한 TLS 암호화(8번과 동일)
      12. Redis를 통한 사용자 인증 및 권한 부여(ACL)(8번과 동일)
      13. AWS Graviton2 인스턴스 유형 지원
      14. VPC, Cloudwatch, CloudTrail, AWS SNS 서비스와의 통합
      15. 완전 관리형 소프트웨어 패치 및 업그레이드 지원
      16. 관리 API를 위한 AWS IAM(Identity and Access Management) 통합 및 태그 기반 액세스 제어
    3. 주요 기능
      1. Cluster
        1. MemoryDB 서비스를 운영하는 하나 이상의 노드 모음 (서비스의 개념)
        2. Shard는 Memory DB Set 단위들의 모임으로 Cluster 내에 존재
          1. Noes ⊂ Shard ⊂ Cluster  = 서비스 DB
        3. Memory DB Set 에는 하나의 Primary 와 최대 5개의 Replica 노드들을 보유 가능
        4. Primary 는 read/write 가능하며, Replica node들은 only read 만 처리
        5. Primary 장애 시 replica node들 중 하나를 primary 로 승격
        6. cluster 생성 시 redis 버전을 지정
        7. cluster 내 Memory DB 기능
          1. cluster 추가
          2. cluster 수정
          3. cluster 스냅샷 가져오기
          4. cluster 삭제
          5. cluster 내 요소 보기
          6. cluster 에 비용 할당 태그 추가 / 삭제
      2. Nodes
        1. MemoryDB 구성 중 가장 작은 단위 (EC2 기반)
        2. 클러스터에 속하며, cluster 생성 시 정해진 버전의 엔진 기반
        3. 필요한 경우 클러스터의 노드를 다른 유형으로 up / down 가능
        4. 단독으로 up / down 가능은 체크 필요
      3. Shards
        1. 하나의 샤드에는 1~6개의 노드로 구성되며, primary 1개에 5개의 replica 로 구성
        2. MemoryDB Cluster는 항상 적어도 하나의 샤드로 구성
        3. 클러스터 내 최대 500개의 샤드를 생성 가능
          1. 최대 500개 노드를 가질 수 있으므로, 1샤드=1 Primary 노드로 하는 경우 500샤드 구성 가능
          2. 단, IP주소가 충분한지 체크 필요
      4. Parameter groups
        1. parameter group 을 적용함으로써 각기 다른 parameter 를 적용 가능
        2. RDS 와 동일 개념
      5. Subnet Groups
        1. VPC 내 subnet group 으로 구성
      6. Access Control Lists
        1. Redis ACL 규칙을 적용 가능 (Access Control List)
      7. Users
        1. 이름과 암호를 가진 User를 생성하여 접속 가능

        2. 2. 사용자는 ACL 구성원
  2. Redis vs Elasticache Redis vs MemoryDB for Redis
    1. 성능 : Elasticache 가 Memory DB 보다 쓰기 읽기 성능이 더 좋음
  Redis ElastiCache for Redis MemoryDB for Redis
내구성 AOF, RDB 로 내구성 처리
(AOF 파일에 쓰기 전 장애 시 데이터 손실 발생 가능성)
Primary 리턴 응답이라, Replica node에 데이터 적재 전 장애 시 손실 발생 가능성 존재
Redis 데이터구조 및 API
내구성이 뛰어난 Inmemory DB (장애 시 무손실 복구)
(Transaction log 까지 작성 후 응답이기 때문에 무손실 가능)
Redis 데이터구조 및 API
성능 12만/sec read/write : μs (마이크로초) read : μs (마이크로초)
write : ms (한자리 Millisecond)
Cluster mode Cluster mode 활성화 비활성화 모두 가능 cluster mode 활성화, 비활성화 모두 가능 cluster mode 활성화 필수
접속 redis-cli 로 접속
백업
  • 조건부 RDB 백업 가능
  • AOF 로 모든 DML 쿼리 저장
  • 24시간 동안 20개까지 스냅샷 생성 제한
    • cluster mode에서만 백업
  • 해당 Region에서 수동 스냅샷 보유 개수 제한은 없음
  • 24시간 동안 20개까지 스냅샷 생성 제한
    • cluster mode에서만 백업
  • 해당 Region에서 수동 스냅샷 보유 개수 제한은 없음
복원
  • RDB 시점 복원 가능
  • AOF 이용하여 원하는 명령문까지 복원 가능
  • RDB 스냅샷 복원
  • 별도의 Replica node가 없을 경우 유실(마지막 스냅샷 이후 부터 유실)
  • RDB 스냅샷 복원
  • 특정시점복원은 불가 (Point in  time Recovery 불가)
  • Transaction log를 이용하여 장애 최종 복원 가능
고가용성 replica
shard 구성
Replica
Shard 구성
 
replica node의 복제가 실패하는 경우
  • 실패 노드를 감지하여 오프라인 전환 및 동일한 AZ에 교체노드를 실행하여 동기화 진행
MemoryDB Multi-AZ primary 장애
  • MemoryDB에서 Primary 오류 감지하면, replica node들 중 primary 정합성체크 후 primary 승격 후 다른 AZ에 있는 primary를 spin up 이후 동기화 진행
    (다른 AZ의 primary 를 spin up 이후 동기화 하는 것보다 더 빠름)
복제 replica 구성
  • async 복제
    • rdb로 먼저 전체 복제
    • 복제 버퍼 내용 복제
replica 구성
  • async 복제
    • rdb 전체 복제
    • (Reserved Memory) 내용 복제
transaction log를 사용하는 async 복제
  • transaction log에 저장(영구저장)하므로 데이터 손실될 위험이 없음
  • Multi-AZ 강력히 권장
  1. 가격 및 Region
    1. 가격
      1. https://aws.amazon.com/ko/memorydb/pricing/ 참고
      2. Elastic Cache 보다 하루 1달러 더 비싸다고 공유 받음
    2. 지원 region
      1. 현재 지원하고 있는 내역 리스트
      2. US East (N. Virginia), US East (Ohio), US West (Oregon), US West (Northern California), EU (Ireland), EU (London), EU (Stockholm), Asia Pacific (Mumbai), Asia Pacific (Seoul), Asia Pacific (Singapore), Asia Pacific (Sydney), Asia Pacific (Tokyo),  Canada (Central), and South America (Sao Paulo)  - 21년10월 정보

 

참고

https://docs.aws.amazon.com/memorydb/latest/devguide/what-is-memorydb-for-redis.html
https://docs.aws.amazon.com/memorydb/latest/devguide/components.html

Elasticache vs MemoryDB 성능 : https://www.sentiatechblog.com/benchmark-series-amazon-memorydb-and-how-it-stands-compared-to-amazon
https://youtu.be/Jbq_XZMZEKY

반응형
반응형

해당 문서는 "Real Mysql 8.0" 서적을 참고하여 도출한 내용 입니다.

(아래 링크는 전혀 수익의 댓가가 없습니다. 오로지 공유 목적 입니다.)

https://book.naver.com/bookdb/book_detail.nhn?bid=20877661 

 

Real MySQL 8.0 1

MYSQL 서버를 활용하는 프로젝트에 꼭 필요한 경험과 지식을 담았습니다!《REAL MYSQL 8.0》은 《REAL MYSQL》을 정제해서 꼭 필요한 내용으로 압축하고, MYSQL 8.0의 GTID와 INNODB 클러스터 기능들과 소프트

book.naver.com

 

  • General log 는 모든 쿼리가 남아 쿼리의 내역을 모두 확인이 힘든 경우 발생
  • Percona의 pt-query-digest 를 이용하여 general log를 분석 가능
  • RDS MySQL 5.7.19에서 발생한 General log 를 이용하여 아래 테스트를 진행
Real Mysql 8.0 (151 page)
Percona에서 개발한 Percona Toolkit 의 pt-query-digest 스크립트를 이용하면 쉽게 빈도나 처리 성능별로 쿼리를 정렬해서 살펴볼 수 있다.

반응형

현재 Local machine이 Windows 라 percona toolkit 을 바로 설치할 수 없었고, WSL 를 이용하여 진행 했습니다.

percona tookit 설치 진행

Percona-toolkit : https://www.percona.com/doc/percona-toolkit/3.0/installation.html

 

Installing Percona Toolkit

Installing Percona Toolkit

www.percona.com

WSL 설치

https://docs.microsoft.com/ko-kr/windows/wsl/install

 

WSL 설치

wsl --install 명령을 사용하여 Linux용 Windows 하위 시스템을 설치합니다. Ubuntu, Debian, SUSE, Kali, Fedora, Pengwin, Alpine 등 원하는 Linux 배포판에서 실행되는 Windows 머신에서 Bash 터미널을 사용할 수 있습니

docs.microsoft.com

percona-toolkit 설치

이렇게 설치까지 끝나고 나면 직접 General log를 AWS RDS 에서 다운받고 분석 진행 하면 됩니다.

 

여기서 WSL 로 파일 복사는 간단합니다.

windows 폴더에서 아래 위치를 찾아가서 옮기면 됩니다.

 

C:\Users\<컴퓨터명>\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_<고유번호?>\LocalState\rootfs\home\<유저>

General log를 복붙하면 쉽게 파일 옮겨진 것을 확인 가능

general log를 pt-query-digest 로 분석 진행 합시다.

명령어 : pt-query-digest --type='genlog' General로그파일명 > 분석파일명
$ pt-query-digest --type='genlog' mysql-general.log.2021-10-28.0 > db5-2-general.log

실재 실행한 내역

  • 실행하면 아래와 같이 분석 완료까지 얼마나 남았는지 시간과 비율을 보여줘서 좋더군요.

Output 파일 내용

General log 분석에 많은 도움이 되었습니다!

 

Slow query 의 경우에는 아래 명령어로 진행 하면 됩니다. 

(Real Mysql 8.0 서적 152page 참고)

 

pt-query-digest --type='slowlog' mysql-slow.log > slowlog.log

 

 

반응형

+ Recent posts