지난 1년간 레디스를 실무에서 처음 접하면서 여러 가지 작업을 했다. 뭔가 명확한 정보를 전달한다기보다는 경험과 트러블슈팅을 기록한다는 느낌으로 끄적여본다.
끄적 1, 레디스는 데이터를 메모리에 저장한다.
레디스를 사용하는 가장 큰 이유 중 하나는 데이터를 디스크가 아닌 메모리에 저장하기 때문이다. 일반적으로 데이터베이스에 데이터를 저장하면 디스크에 이를 보관한다. 이 말은 디스크에 저장되어 있는 데이터를 조회하면 디스크와 메모리와 네트워크를 거친다는 말과 같다. 디스크, 메모리, 네트워크의 경계에서 발생하는 유저 & 커널 스레드 전환 및 버퍼에 데이터를 옮기는 과정 중 가장 느린 디스크에서 데이터를 옮기는 작업이 없으니 당연히 데이터 읽기 및 수정 요청의 응답 속도가 빠를 수밖에 없다. 물론 레디스도 AOF(Append Only File)나 RDB(Snapshot) 방식으로 데이터를 디스크에 저장할 수 있지만, 기본적으로는 메모리 기반이라는 점에서 큰 성능 차이를 가진다.
끄적 2, 레디스는 여러 가지 형식으로 데이터를 저장할 수 있다.
레디스는 키-값 저장소인데, 여기서 값에 해당하는 데이터를 여러 가지 형식으로 저장할 수 있다. 단순히 숫자, 문자도 저장할 수 있지만 여러 가지 자료구조도 지원한다. List, Set, SortedSet, Hash 등 우리가 생각하는 대부분의 자료구조를 레디스의 값으로 사용할 수 있다. 그리고 이 자료구조를 효율적으로 사용할 수 있는 여러 가지 명령어도 함께 제공한다. 예를 들어 List는 Queue에서 제공하는 왼쪽에 값 추가(LPUSH), 오른쪽에 값 추가(RPUSH), 왼쪽의 값 읽고 제거(LPOP) 등의 연산을 지원한다.
끄적 3, 레디스는 많은 문제를 해결한다.
위에서 언급한 특징과 연관된 내용으로 레디스만 잘 써도 애플리케이션 레벨에서 발생하는 문제와 고민을 해결할 수 있다.
여러 서버에서 공통으로 사용해야 하는 데이터를 저장할 때 이 데이터를 빠르게 접근하고 동시성 문제없이 조작해야 할 때 사용 중인 RDB에서 다루기 어려운 형식의 데이터가 생겼을 때 급하게, 혹은 임시로 무언가 저장해야 할 때 단적으로 말하면 대부분의 상황에 대응할 수 있는 데이터가 레디스라고 해도 과언이 아니다. 거기에 복제 설정, 클러스터 설정까지 하면 만능이라고 불러도 될 정도라고 생각한다. 개발자 실수로 레디스에 큰 데이터가 계속 추가되어서 OOM이 발생하지만 않는다면 레디스가 스스로 뭔가 문제가 생겨서 죽는 일은 거의 없다고 보면 된다.
끄적 4, 레디스 키 패턴을 잘 결정해야 한다.
정말 중요하다. 개인적인 의견이지만 키 패턴만 잘 정해도 레디스 운영의 대부분의 문제는 해결된다고 생각할 정도로 키 패턴을 잘 정하는 것이 중요하다. 키가 짧고 길고를 이야기하는 것은 아니다. 내가 생각하는 포인트는 레디스에 저장되어 있는 키 목록을 레디스 조회 없이 알 수 있게 키 패턴을 정하는 것이다.
레디스를 단일 인스턴스 형태로 사용하거나 작게만 사용하는 경우에는 레디스에 저장되어 있는 키를 조회하는 KEYS 명령어를 사용해도 큰 부담이 없다. 비록 KEYS 명령어가 블로킹(blocking) 명령어라 다른 요청을 모두 블로킹시키지는 않지만, 전체 데이터를 탐색해야 하므로 성능 저하를 초래할 수 있다. 운영 환경에서는 주의해서 사용해야 하는 명령어다. 그래서 KEYS 대신 SCAN 명령어를 사용하는 것이 기본이다. SCAN은 다른 연산을 거의 블로킹하지 않는다고 한다.
그런데 여기서 포인트가 있다. KEYS, SCAN 모두 특정 키 패턴에 대해서 레디스에 검색을 하는 명령어다. 하지만 레디스는 키 패턴이 아니라 특정 키의 유무는 바로 알 수 있다. 다시 말하면 레디스에 존재하는 모든 키를 레디스를 조회하지 않고도 알 수 있는 방법이 있다면 운영할 때 굉장히 편하다는 것이다.
레디스를 하드하게 사용하는 곳은 굉장히 큰 용량의 레디스를 사용하고 이 레디스를 수많은 요청량이 많은 서버가 바라보고 있는 경우가 많다. 이 상태에서 단순히 레디스의 데이터를 읽는 연산만 생기더라도 레디스에 부하가 꽤 있을 것이라는 건 누구나 예상할 수 있다. 그런데 만일 레디스에 저장되지 말아야 할 데이터가 저장되었다고 가정해 보자. 설령 KEYS와 DEL 대신 SCAN과 UNLINK를 사용해 부하가 적더라도 커다란 레디스 클러스터를 뒤지는 것은 같은 레디스를 사용하고 있는 다른 모든 서버에 영향을 주기에 부담스러운 일이다. 만일 내가 서버 로그, 혹은 RDB 등 모종의 방법으로 레디스에 저장될 수밖에 없는 모든 키를 만들 수 있다면? 그냥 키 목록만 CSV 파일로 만들어서 스크립트만 돌리면 된다.
이렇게 사용할 수 있으려면 레디스를 조회하지 않고도 레디스 키를 알 수 있도록 키 패턴을 가져가면 좋다. RDB PK, 몽고DB의 도큐먼트 ID 등 뭔가 고유한 값이 레디스 키 패턴에 들어가 있다면 좋겠다. 또한 TTL(Time-To-Live) 설정이나 eviction policy(데이터 자동 삭제 정책)도 함께 고려하면 보다 안정적인 운영이 가능할 것이다.
'Programming' 카테고리의 다른 글
몽고DB 이것저것 (3) | 2025.02.16 |
---|---|
코틀린 하나의 파일에 클래스 하나만 사용하기 vs 여러 개 사용하기 (0) | 2025.01.19 |
한 편으로 끝내기 - 제네릭과 변성(공변성, 반공변성) (0) | 2024.10.13 |
[2023 ver.] 서버 개발자 mac 장비 설정 (0) | 2023.07.22 |
성능 테스트 (0) | 2022.06.01 |