Admin 에 대해 고급까지는 아니지만, 중급까지는 공부합니다. 아키텍처 및 동작 방식까지 공부 합니다. 5명(모집자 포함) 모두 발표 합니다. (하루전에 발표 자료 공유 부탁 드립니다.) 모집 인원은 모두 찾았습니다. Postgresql 운영만 최소 3년 이상 리더 한분 섭외(리더는 내용에 대해 경험에 대해 발표-리더도 발표합니다.) 2주에 한번 합니다. 현생이 힘듭니다...
목차
Postgresql 에 대한 소개
Postgresql 설치
rpm 패키징 설치는 간략하게
Source 설치에 대해서 진행합니다.
원하는 곳에 Log, Data file 지정이 필요
Source 수정까지는 아니지만 필요할때는 코드라는걸 한법 봅시다.
업그레이드 / 다운그레이드
무중단 업그레이드 위주로 테스트
HA
Major 설정값(parameter) 위주로 확인 (메모리, path, character set 등)
Aurora Postgresql 간략하게(자세하게 확인은 맨 마지막에)
Postgresql Architecture
내부 구조에 대해 두리뭉실하게...
client
Server
process
내부 process (Wal, vacuum 등)
memory
Files
계정 및 권한
내부 Architecture 와 연관
Schema, Database, table 에 대한 권한과 권한에 따른 영향
계정에 대한 관리
Transaction 과 Lock 관리
Index
Optimize 와 Hint, Explain
내부 명령어 및 system 테이블
백업 복구
반드시 한번씩 해봅시다.
Full backup / restore, Incremental backup, PITR
옵션도 공부합시다.
Third party 하나 정도 이용해 봅시다.
동작 방식도 이해합니다.
DB 이관 (Oracle to Postgresql)
주의 점
단순 Migration 외의 서로 다른 엔진 특성 상 수정 되어야 하는 설계
모니터링
모니터링 지표들과 조회 방식
Third party tool
그 외 추가 되어야 하는 내용들
참고 사이드
개인적으로 북마크하는 곳이지만, 그 외 많은 숨고 사이트가 있습니다. 공홈 : https://www.postgresql.org/ postgresql dba 커뮤니티 : https://www.postgresdba.com/ 페이스북 통해서 확인 : https://postgresql.kr/ 넘사벽 김두비 : https://kimdubi.github.io/postgresql/
한글로 된 자료도 많지가 않아서 초등이하 수준의 영어를 번역기 돌리고 나쁜 머리로 이해하고 쓰느라 부족한 부분이 많습니다. 부디 저의 글이 도움이 되어, 보다 자세하고 정확한 글들이 나오길 기대하는 마음으로 작성하였습니다.
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 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 에서 읽을 경우 복제가 완료되지 않아 잘못된 데이터를 읽을 수 있음을 의미
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로 인식을 하는 것을 확인
당연히 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;"
lua 엔진은 사용하였지만, get 명령어 같이 조회 하거나 하는 것이 아니기 때문에 lua 메모리 쪽에 적재 되는 것은 없는 것으로 확인
다시 한번 lua 스크립트 실행
동일하게 lua 엔진은 사용하였지만, memory 는 사용 하지 않은 것을 확인
바로 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 의 변화로 모니터링 하는 것으로 우회 하거나, 해당 지표를 직접 조회하여 모니터링 하는 것을 추천 드립니다.