The first release candidate of Redis 4.0 is out

Salvatore Sanfilippo

Redis 4.0 첫 번째 릴리스 후보가 나왔습니다

아직 안정 버전은 아니지만 곧 안정 버전이 될 예정이고, Redis를 우리 사용자들에게 더 유용하게 만들어 줄 긴 목록을 들고 왔습니다. 마침내 Redis 4.0 릴리스 후보 1이 나왔고, 3.4가 아니라 감히 스스로를 4.0이라 부릅니다. 제게 시맨틱 버저닝은 중요한 것이 아닙니다. 제가 좋아하는 방식은 버전 번호와 그 점프를 이용해 새 버전이 어떤 의미를 갖는지 전달하는 것이고, 이번 경우에 4.0은 “이건 진짜 대박이다”라는 뜻입니다.

사실 Redis 4.0에는 Redis가 진작부터 가지고 있었어야 할 것들이 많이 들어 있습니다. 한 명의 개발자가 북두의 권의 켄시로처럼 열 명으로 분신해 코딩을 시작할 수 있는 다른 세상이라면 말이죠. 하지만 아무리 새로운 vim 단축키를 열심히 배워도, 분신술만큼은 제 단축키 목록에 없습니다.

어쨌든 마침내 4.0에서 이런 것들을 많이 해냈습니다… 그리고 여기에 주요 기능 목록과 간단한 설명, 더 알아볼 수 있는 링크를 정리했습니다.

1. 모듈

아마 이미 아시겠지만 Redis 4.0에는 모듈 시스템이 생겼습니다. RDB/AOF로 영속화되는 새로운 자료형을 구현하거나 논블로킹 명령을 만드는 등 꽤 멋진 일들을 할 수 있게 해 주는 시스템입니다. 핵심은 이 모든 것이 코어와 완전히 분리된 고수준 추상 API로 이루어진다는 점이라, 여러분이 작성한 모듈은 이후 Redis 릴리스에서도 계속 동작할 것입니다. 저는 모듈을 이용해 Redis 안에서 직접 학습시킬 수 있는 신경망 자료형인 Neural Redis를 만들었고, 많은 분들이 정말 흥미로운 작업들을 하고 있습니다. 새로운 레이트 리미팅 명령(Rust로 구현되었습니다!), Redis 위에서 동작하는 그래프 DB, 세컨더리 인덱스, 시계열 모듈, 전문 검색 인덱싱 등 다양한 것들이 나오고 있고, 제 느낌엔 이제 시작일 뿐입니다.

이는 Redis가 코어를 최소는 아니더라도 최소한 대다수 사용자에게 유용하고 많은 사람이 필요로 하는 꽤 범용적인 것들만 담아둔 채로 새로운 영역을 커버하며 성장할 수 있게 할 뿐만 아니라, Redis나 데이터베이스, 캐싱 등 Redis가 무엇이든 간에 그것과 관련 없는 무언가를 만들려는 경우에도 많은 작업에서 네트워크 서버를 새로 작성해야 하는 문제를 피할 잠재력을 가지고 있습니다. 즉, Redis의 “인프라”, 즉 프로토콜이나 이미 만들어진 클라이언트 등을 활용하기 위해 모듈을 작성하기만 하면 되는 것이죠. 그래서 저는 이 기능에 대해 좋은 예감이 듭니다. 코어에는 부담이 없고, 더 과감한 일을 하고 싶은 사용자에게는 자유가 생기니까요.

2. 리플리케이션 버전 2

그래서 운영 관점에서 보면 프로덕션에서 아주 유용할 겁니다. 과거 어느 시점에 우리는 “PSYNC”라고 불리는 것을 도입했습니다. 마스터와 슬레이브 사이의 연결이 끊겨도 두 인스턴스가 끊긴 지점부터 이어서 진행할 수 있게 해 주는 새로운 마스터-슬레이브 프로토콜이었죠. 그전에는 마스터와 슬레이브 사이 리플리케이션 연결이 한 번이라도 끊기면 전체 동기화가 일어났습니다. 마스터에서 RDB 파일을 생성하고, 전송하고, 슬레이브에서 로드하는 식이죠. 어떻게 동작하는지 아실 겁니다. 그래서 PSYNC는 정말 큰 개선이었습니다. 하지만 충분하지는 않았죠…

페일오버 상황에서는 PSYNC가 충분하지 않았습니다. 슬레이브가 마스터로 승격되면, 기존 마스터와 리플리케이션하던 슬레이브들은 새로 승격된 슬레이브에 연결해 PSYNC를 할 수 없었습니다. 전체 재동기화가 필요했죠. 이는 좋은 상황이 아니고 Redis Cluster에도 좋지 않습니다. 하지만 이를 고치려면 리플리케이션 프로토콜을 변경해야 했습니다. 인스턴스들 사이에 공통된 리플리케이션 히스토리가 존재하는 한, 어떤 토폴로지 변경 후에도 부분 재동기화가 동작하도록 확실히 하고 싶었기 때문입니다.

그래서 필요한 첫 번째 변경은 “체인 리플리케이션”이 동작하는 방식에 관한 것이었습니다. 즉, 슬레이브의 슬레이브의 슬레이브… 이들은 어떻게 동작할까요? 예를 들어 A가 마스터이고 다음과 같은 구조가 있다고 해 보죠.

A —> B —> C —> D

A는 B의 마스터이지만 B는 C의 마스터인 식입니다. Redis 4.0 이전에는 B가 A로부터 리플리케이션 프로토콜을 받았습니다. 리플리케이션 프로토콜은 보통 쓰기 명령의 스트림이죠. B는 C에 대한 마스터로서 내부적으로 A가 하던 일을 그대로 했습니다. 매 쓰기 때마다 C에 전달할 적절한 리플리케이션 프로토콜을 다시 생성하는 식이었고, 이후도 마찬가지였습니다.

이제는 대신 B가 A로부터 받은 것을 그대로 C에 프록시하고, C도 D에 대해 똑같이 합니다. 모든 하위 슬레이브가 이제 동일한 바이트 스트림을 받게 되므로, 특정 히스토리에 “태그”를 붙이고 그 태그와 오프셋을 이용해 공통점이 있는 경우 항상 이어서 진행을 시도할 수 있습니다.

마스터 자체도 슬레이브로 전환될 때 이제 새로운 마스터와 PSYNC를 할 수 있습니다. 그리고 슬레이브도 이제 리플리케이션 태그와 오프셋을 저장하는 RDB 파일 안의 정보를 이용해 “클린” 재시작 이후에도 보통 마스터와 PSYNC를 할 수 있습니다.

제대로 동작하게 만들기 위한 세부 사항은 이보다 더 복잡하지만, 어쨌든 요점은 가능하면 전체 재동기화로 인한 불편을 겪지 않게 하자는 것입니다. 그리고 PSYNC v2는 이를 꽤 잘 해내는 것 같습니다. 직접 써 보시고 이 기능에 관심 있으시면 알려 주시기 바랍니다.

3. 캐시 축출 개선

이 부분에 대해서는 몇 달 전에 전체 글을 쓴 적이 있습니다: http://antirez.com/news/109. 그래서 TL;DR만 전해 드리겠습니다. 이제 LFU(Last Frequently Used)가 생겼고, 다른 모든 정책도 더 견고하고 빠르고 정밀한 구현으로 바뀌었습니다. 그러니 캐싱 유즈 케이스에는 큰 소식입니다. 이 주제에 관심 있으시면 전체 글을 읽어 보세요. 정보가 정말 많습니다.

4. 논블로킹 DEL과 FLUSHALL/FLUSHDB

코드명은 “lazy freeing of objects”인데, 멋진 기능에 비하면 좀 싱거운 이름입니다. UNLINK라는 새로운 명령이 있는데, 데이터베이스에서 키 참조만 삭제하고 실제 메모리 할당 해제는 별도 스레드에서 수행합니다. 그래서 거대한 키에 대해 DEL 대신 UNLINK를 사용하면 서버가 블로킹되지 않습니다. 더 좋은 점은 FLUSHALL과 FLUSHDB의 ASYNC 옵션을 이용하면 원한다면 전체 DB나 인스턴스 안의 모든 데이터에 대해 같은 일을 할 수 있다는 겁니다. 두 Redis 데이터베이스의 내용을 교환하는 새로운 SWAPDB 명령과 함께 사용하면 FLUSHDB ASYNC가 꽤 흥미로워집니다. 예를 들어 DB 1에 새 버전의 데이터를 채운 뒤 SWAPDB 0 1을 실행하고 옛 데이터가 들어 있는 데이터베이스를 FLUSHDB ASYNC로 비운 다음, 또다시 새 버전을 만들어 같은 과정을 반복할 수 있습니다. 전체 DB를 비우는 동작이 더 이상 블로킹되지 않게 되었기 때문에 이제야 가능해진 일입니다.

UNLINK가 DEL의 기본 동작이 아닌 데에는 이유가 있습니다. 저는 알고 있습니다… 말할 수 없지만요(**).

5. 혼합 RDB-AOF 영속화 포맷

선택 사항으로, 이 기능을 활성화하면 이제 AOF 재작성이 AOF 파일 앞에 RDB 파일을 붙이는 방식으로 수행됩니다. 생성과 로드 모두 더 빠릅니다. 이는 특정 환경에서 매우 유용하겠지만 AOF 파일을 덜 투명하게 만들기 때문에 일단은 선택 사항으로 두었습니다. 오랫동안 이야기되던 기능이 마침내 들어왔습니다.

6. 새로운 MEMORY 명령

저는 이 기능이 정말 마음에 듭니다. 예전에 LATENCY DOCTOR를 도입했을 때 메일링 리스트에서 “제 Redis가 느려요”라는 불만이 극히 일부로 줄어들었던 만큼이나요. 이제 메모리 문제에 대해서도 같은 것이 생겼습니다.

127.0.0.1:6379> MEMORY DOCTOR
Hi Sam, this instance is empty or is using very little memory, my issues detector can't be used in these conditions. Please, leave for your mission on Earth and fill it with some data. The new Sam and I will be back to our programming as soon as I finished rebooting.

판권 소유자들이 SF 대사에서 영감을 받았다고 저를 고소할지도 모르겠지만 괜찮습니다. 제가 감옥에 가게 되면 오렌지 좀 가져다 주세요.

MEMORY는 그 외에도 훨씬 더 많은 일을 합니다.

127.0.0.1:6379> MEMORY HELP
1) "MEMORY USAGE <key> [SAMPLES <count>] - Estimate memory usage of key"
2) "MEMORY STATS                         - Show memory usage details"
3) "MEMORY PURGE                         - Ask the allocator to release memory"
4) "MEMORY MALLOC-STATS                  - Show allocator internal stats"

USAGE 서브 명령의 메모리 사용량 리포팅도 매우 유용하겠지만, “STATS”가 제공하는 심층 정보도 마찬가지입니다.

지금으로선 이 모든 것이 전혀 문서화되어 있지 않으니, 도대체 무슨 일을 하는지 알아내는 재미를 느껴 보세요.

7. Redis Cluster가 이제 NAT / Docker 호환

하지만 사실 이것 때문에 안 좋은 소식도 있습니다. 노드 간 통신에 쓰이는 “클러스터 버스”의 바이너리 프로토콜이 바뀌었기 때문에 4.0으로 업그레이드하려면 Redis Cluster 전체를 재시작해야 합니다. 이 NAT / Docker 수정에 속아 넘어간 셈이라 죄송합니다. 용서해 주세요. 하위 호환성을 유지하려 노력했지만, 완전히 어색한 방법을 쓰지 않고서는 쉽게는 물론 어렵게도 이를 달성할 방법이 없었습니다.

이 기능은 예제 redis.conf 파일에 설명되어 있습니다. 다른 기능들에 비해 제가 이 기능에 대해 조금 덜 신나 한다는 걸 느끼시겠죠?

뭐… 대략 이 정도가 주요 내용인 것 같습니다. 원하시면 릴리스 노트도 여기서 읽어 보실 수 있습니다: https://raw.githubusercontent.com/antirez/redis/4.0/00-RELEASENOTES

안정 버전이 나오기까지의 예상 일정은 늘 그렇듯 미정입니다. 대략 2~4주마다 새로운 RC를 릴리스할 계획입니다. 버그의 심각성과 제보 빈도 측면에서 버그가 눈에 띄게 줄어들면 그때가 Redis 4.0 최종 버전이 될 때입니다. 하지만 업데이트해야 할 문서도 많으니 할 일은 충분합니다.

이번 릴리스에 기여해 주신 모든 분들께 깊이 감사드립니다. 많은 분들이 중요한 방식으로 기여해 주셨습니다. 위 릴리스 노트에는 모든 커밋 목록이 있으니 훑어보시면 커미터들의 이름을 확인하실 수 있습니다.

이 모든 것을 가능하게 해 준 Redis 커뮤니티와 Redis Labs에 감사드리며, 특히 Redis를 사용해 일상의 문제를 잘 해결하며 일을 처리해 내는 모든 개발자분들께 감사드립니다. 코딩하는 재미 말고도, 바로 그게 핵심이니까요.

P.S. 새 코드를 더 빨리 받는 방법은 Github에서 '4.0' 브랜치를 가져오는 것입니다. 저장소는 늘 그렇듯 antirez/redis입니다.

** UNLINK가 DEL의 기본 동작이 아닌 이유에 대한 더 자세한 정보는 https://news.ycombinator.com/item?id=13091370 에서 확인하세요.

원문은 Salvatore Sanfilippo님이 에 게재했습니다.

이 글은 muse-spark-1.2-contributor 모델을 사용해 번역했습니다.