파이문

Redis 에서 같은 키로 다른 값 사용하기 본문

컴퓨터 과학/데이터베이스

Redis 에서 같은 키로 다른 값 사용하기

민Z 2020. 6. 28. 15:28

☢️ 주의 레디스를 모르는 상태에서 의식의 흐름대로 조사하고 정리한 내용입니다.

발단

Redis에서 같은 키를 사용하는 서로 다른 어플리케이션이 있었다. 가장 베스트는 Redis 서버를 아예 분리해서 각각의 어플리케이션이 분리된 Redis 를 이용하면 되겠지만, 남는 서버도 없고 어플리케이션의 서비스 크기가 크지 않고 (메인 서비스가 아니고 부가적인 서비스였다.) 그러다 보니 서버 발주는 오바였다.

 

MySQL 이 Database 를 여러개 두는 것 처럼 Redis 도 그럴 수 있지 않을까? 생각하였는데, 찾아보니 Redis 도 Database 를 여러개 둘 수 있었다.

 

아무 명령도 치지 않았고, 그냥 기본적인 것들로 사용하였다면 DB 는 자동으로 0 번이다. 만약 다른 DB 를 사용하고 싶다면

select <db_num>

위와 같이 cli 상에서 DB 번호를 지정하면 된다. 숫자는 최대 16까지 가능하며, 각각의 DB 는 분리되어있기 때문에 DB 0 과 DB 1 에 같은 키, 다른 값을 사용할 수 있다.

 

결론부터 말하자면 이 방법은 꼼수 of 꼼수였고 Redis SELECT 도큐먼테이션에도 추천하지 않는 방법이다.
이런 경우엔 서로 다른 키를 쓰는 것이 맞다.

사실 이미 Redis 는 Cluster 로 구성 되어 있고, 이 Cluster 모드에서는 DB select 를 제공하지 않았다. 아래는 Redis Cluster 스펙에 적혀있는 문구이다.

Redis Cluster does not support multiple databases like the stand alone version of Redis. 
There is just database 0 and the SELECT command is not allowed.

Cluster 란?

Redis cluster 는 데이터를 분산 시켜 가용성을 확보하는 솔루션이다. (샤딩/파티셔닝 개념) 노드 중 일부가 장애나도, 다른 노드들이 살아 있기 때문에 시스템엔 문제가 없게 프로세스는 중단되지 않는다. 물론 대부분의 노드에 장애가 생긴다면 문제가 되긴 하지만. (자세한 내용은 레디스 해시 슬롯 참조)

 

😔 사실 솔직히 말하자면 왜 Cluster 에서 multiple database 를 지원하지 않는지 모르겠다. Cluster 스펙에 위반 된다고 하는데, 왜 위반 되는 건지도 모르겠고.... 더 공부해야 한다.

 

결국 DB Select 를 사용하기 위해선 standalone 으로 띄워서 마스터-슬레이브 구조로 가야 하는데 그럴 경우 Failover 가 걱정 되었다.

 

그렇게 해서 찾아본 것이 sentinel 이였다

Sentinel 이란?

Sentinel 은 단순하게 말하면 (사실 정말 간단히 리서치 해서 자세히는 모름) master-slave 구조에서 master 가 다운 되었을 시 다른 slave 들 중에 master 를 선출하는 또 다른 프로세스? 인 것이다.

 

그러니까 결국 서버에서 redis 를 띄우면, redis-sentinel 이란 것도 띄워야 한다. 물리적으로 같은 서버에서 띄워도 되고, 다른 서버에서 띄워도 된다. (사실 같은 서버에서 띄우는 것은 bad setup이다.)

 

한마디로 auto failover 를 제공해주는 것이라고 보면 될 것 같다. (cluster 모드도 failover 가 가능하다. cluster 모드는 보통 마스터는 3대로 두고 슬레이브는 각각 마스터와 1:1 로 구성한다고 한다.)

Sentinel 은 어떻게 사용할까?

우선 레디스를 master-slave 구조로 띄워야 한다. 마스터는 그냥 띄우면 되고 슬레이브를 띄울때 config 를 조정한다.

중간에 replicaof master-ip 를 추가 하면 된다. 다른 예제에서는 slaveof 로 추가하라고 하는데 아마 버젼 차이 때문인 것 같다. 참고로 내가 테스트했을 시 레디스 버젼은 5.0.3 이었다.

 

이렇게 각 슬레이브에 마스터 ip 를 적어주면 우선은 master-slave 구성은 완성 된 것이다.

 

다음은 Sentinel 을 띄운다. 나는 물리적으로 같은 서버에 띄웠다. sentinel 은 sentinel.conf 라는 파일이 있고, 여기에 같은 방법으로 마스터 ip 를 적어주면 된다. (정확히 어떤 문구였는지는 까먹음)

 

레디스를 띄울때 redis-server 였다면 sentinel을 띄울땐 redis-sentinel 로 띄우면 된다. 그리고 뒤에 각각의 config 를 바로 넣어주면 알아서 그 config로 띄워진다.

 

1대의 master, 2대의 slave 그리고 3개의 sentinel 로 테스트 해보았고 마스터를 다운 시켰을 때 다른 slave가 master로 선출되고 해당 config 들에서도 기존 마스터가 아닌 새로운 마스터의 ip 로 오버라이트 되는 것을 볼 수 있었다.

 

만약 제대로 안된다고 하면 bind 로 해당 서버에 접근 가능한지 우선 확인해보고 그 다음에 ip 를 제대로 적었는지 보면 될 것 같다.

언제 cluster를 사용하고 언제 sentinel 을 사용할까?

우선 cluster 는 하나가 장애가 나면, 장애가 난 노드에 담당하는 데이터는 손실될 가능성이 있다. sentinel 로 구성하면 데이터 손실 걱정은 없다. 어차피 다 복제 되었으므로.

 

이렇게 보면 cluster 가 더 안좋은 것 같지만 대신 cluster 는 샤딩을 제공한다. sentinel은 단독 모드에다가 master-slave라 단순히 복제라서 데이터 사이즈가 엄~청 커지면 스케일업을 해야하는데 cluster 는 스케일아웃을 하면 된다.

 

그리고 sentinel 로 구성해도 마스터 선출만 자동이지, 노드를 다시 띄우는건 수동이다. (클러스터는 내가 구성안해서 잘 모르겠음)

결론

갑자기 결론이다. 우선 (나의 경우) 최초에 레디스가 cluster 로 구성되어 있었고 단순히 캐시 사용이기 때문에 유실은 걱정하지 않아도 되었다. (디스크에 저장도 하지 않는다.) 따라서 sentinel 로 가야할 이유가 없었으며, 목적이 같은 키를 같은 Redis 에서 사용할 수 없을까? 이기도 하였다.

 

그래서 나는... 그냥 키를 변경했다. (?????) 데이터에 TTL 이 적당히 짧게 주어져있었고, 데이터도 메모리 대비 충분했다. 

 

키는 API 마다 Prefix 를 서로 다르게 주는 것으로 했다. 우리 팀은 인원도 적고, 문서화만 잘 해두면 된다고 생각하였기 때문이다. (그리고 실제로 서로 그렇게 공유하고 넘어갔다.)

 

만약 Cluster 모드로 하지 않아도 된다면 Standalone 에서 DB Select 를 사용하면 된다. DB Select 도 결국 같은 키로 다른 값을 사용할 수 있는 해결 방법 중 하나이기 때문이다. (Redis 에서 Multiple databases 가 정말 베스트 솔루션인지는 논외이다. stackoverflow.com/a/36498590/4547125)

 

가끔은 기술을 이것저것 도입하는 것 보다 논리적인 개념을 넣는게, 시간, 비용 대비 효율이 더 나은 것 같다.

참고

Comments