본문 바로가기

개발/Redis

성능 향상 + 메모리 절약을 충족시키며 Redis 사용하기

개요


프로젝트에서는 좋아요 기능이 있습니다. 

 

첫 설계에서 좋아요 관련 CRUD 작업은 RDB에서 수행했습니다.

 

하지만 lost update를 방지하기 위해 RDB에 배타락을 걸어, select for update로 이를 처리했는데 이러한 방식은 성능상에 악 영향을 미치는 작업이었습니다.

 

이를 해결하기 위해 인 메모리 데이터베이스인 Redis를 사용하고, 분산락을 이용해서 좋아요 관련 작업을 수행해서 성능을 향상시켰습니다. 

 

여기서 문득 의문점이 생겼습니다.

 

만약 좋아요 데이터가 1억개가 된다면??

 

그러면 시스템 메모리 사용량이 상당히 높아질 것이고, 값 비싼 비용을 지불해서 캐시 서버를 여러대 늘려야만 해결할 수 있을 것입니다.

 

그래서 이 문제를 해결하고자 아래 플로우대로 작업을 수정해보겠습니다

 

 

 

 

좋아요 조회 로직


 

로직은 아래의 순서로 동작합니다.

 

1. 좋아요를 누른 유저가 유효한 유저인지 확인

2. Redis에서 like 수 조회

3. 조회가 실패하면 RDB에서 like 수 조회

4. 조회한 데이터를 Redis에 반영

5. 데이터 반환

 

이렇게하면 캐싱된 데이터를 조회할 경우 Redis에 저장된 데이터를 바로 반환할 수 있게됩니다.

 

만약에 데이터가 캐싱되어있지 않다면 RDB - Redis를 둘다 거쳐야하기 때문에 성능상에 불이익이 있지 않을까? 라고 생각할 수 있습니다.

 

하지만 우리가 인스타그램을 볼 때도 많은 사용자들이 조회한 피드들이 추천되듯, 데이터들은 기존에 대다수의 유저가 조회한 데이터들만 보는 경우가 많기 때문에 캐싱하는 편이 훨씬 비용이 절감됩니다.

 

 

 

 

 Redis AOF / RDB 전략


이전 과정들을 통해 Redis를 이용한 캐싱을 구현하며 한가지 의문이 생겼습니다.

 

Redis에 캐싱된 데이터가 RDB에 반영되기 전에 Redis 서버가 죽어버리면 데이터가 다 유실되는게 아닐까??

 

이 문제를 해결하기위해 Redis에 백업 전략을 세워보겠습니다.

 

 

 

 

RDB


RDB는 사용자가 지정한 시간마다 Redis에 존재하는 데이터의 스냅샷을 만들어, Redis를 재 시작할 때 스냅샷을 기반으로 데이터를 백업하는 전략입니다.

 

 

하지만 이 방식은 실제 운영환경에서 사용하면 두가지 문제가 생길 것이라 예상했습니다.

 

1. 데이터 스냅샷을 생성하는 동안 Redis 서버에 부하가 가해진다.

2. 스냅샷이 생성된 이후에 Redis 서버가 죽었을 때, 스냅샷 생성 시각 ~ Redis 서버가 죽은 시각에는 데이터가 유실됩니다.

 

이러한 문제를 예방하기 위해 AOF에 대해 알아보겠습니다.

 

 

 

 

AOF 


AOF 방식은 Redis에 대한 Create, Update 작업을 로그로 저장해, Redis 서버를 재 시작할 때 해당 로그를 순차적으로 실행시켜서 백업하는 방식입니다.

 

 

 

이렇게되면 서버가 언제 죽어도 데이터를 모두 복원시킬 수 있기 때문에 데이터 유실을 최소화하며, 안정적인 서버 구현이 가능해집니다.

 

하지만 AOF 방식도 문제가 아예 없는것은 아닙니다.

 

만약 오랜 시간동안 죽지않을 경우 비 휘발성 메모리 영역에는 상당히 많은 로그 데이터가 쌓일 것 입니다. 

 

이런 서버가 죽게될 경우 해당 로그들을 모두 실행시켜야하기 때문에 백업하는 시간이 상당히 오래걸릴 것 입니다.

 

일단은 데이터 유실을 최소화하는 것이 목적이므로 AOF 방식을 적용해보겠습니다.

 

 

 

AOF 적용 


 

docker-compose를 이용해 redis를 구동하고있어 설정은 간단했습니다.

 

redis 설정정보에 aof를 사용한다는 command만 추가해주면 적용이 가능합니다.

 

 

 

docker 컨테이너에 접근한 뒤 "CONFIG GET appendonly" 명령어로 설정이 되었는지 확인해줍니다.

 

만약 설정이 안되었을 경우 appendonly의 value값으로 no가 반환됩니다.

 

그러면 Redis에 보내는 요청이 로그 형태로 올바르게 저장되는지 테스트해보겠습니다.

 

 

우선 mykey라는 key 값과 myvalue라는 value 값을 추가한 뒤, 이를 조회해보겠습니다.

 

 

이후 로그 파일이 저장되는 appendonly.aof.1.incr.aof 파일에 접근해보면

 

 

 

GET 요청은 로그에 저장되지 않고, SET 요청만 정상적으로 로그가 저장된 것을 확인할 수 있습니다.

 

이 파일을 이용해 추후 Redis 서버가 죽었을 때도 데이터 유실없이 서버를 재시작 시킬 수 있습니다.

 

 

결론 


성능 향상을 위해 RDB --> Redis로 데이터를 캐싱하고, Redis의 AOF를 이용해 데이터 유실을 방지하는 전략을 세워봤습니다.

 

현재까지 구현한 코드에서 고려할 부분이 더 있습니다.

 

만약 Redis 서버가 죽었을 경우 좋아요 조회 요청을 Redis가 아닌 RDB로 보내야하는 것입니다.

 

이는 다음 포스팅에서 구현해보도록 하겠습니다.

'개발 > Redis' 카테고리의 다른 글

Redis AOF에서 성능 저하를 방지하는 방법  (2) 2024.11.11