HTTP 200 OK

Memento mori & Carpe diem

Redis

Redis를 k8s에 업로드할때 경험한 이슈들

sjoongh 2023. 1. 30. 22:06

개요

1. Redis를 findByUserId와 같은 형식으로 검색을 하고 싶어 @Indexed 어노테이션을 활용해 Entity class에 선언해두었다.

@RedisHash("test", timeToLive = 86400)
class TemporaryGiftEntity(
    @Indexed
    val id: String = UUID.randomUUID().toString(),
    @Indexed
    val purchaseId: String,
    val orderName: String,
    ...
)
  • 위와 같이 설정을 해놓는다면 Redis에 저장될때 id와 purchaseId가 각각 key값으로 저장되기 때문에 기존의 RDBMS 검색조건들과 같이 findByIdAndPurchaseId 와 형식으로 검색조건을 지정할 수 있다.

 

 2. 하지만 위와 같이 @Indexed를 사용하면 Redis에는 @Indexed만큼 key가 생성되고 해당 엔티티를 통해 redis에 저장했을때 @RedisHash에 설정한 key값을 제외하고는 해당 객체와 연관된 다른 모든 key는 TTL시간이 지나도 영구적으로 삭제되지 않는다.

 

  •  하지만 이 경우는 설정한 TTL시간은 지났으므로 만료키인 상태이긴 하다.(조회할 수 없음), 그러나 메모리 용량을 계속 잡아먹는 단점이 있다..

 

 3. 내가 구현하고 싶은 것은 임시테이블이다. 때문에 영구적으로 히스토리가 남을 필요가 전혀없었다. 그렇기 때문에 설정한 TTL시간이 지나면 무조건적으로 사라지는 것을 원했고 RedisConfig에 아래와 같이 추가해주었다.

@EnableRedisRepositotories(enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP)
  • 해당 어노테이션은 RedisConfig라는 클래스를 생성하여 추가해주었다. 해당 어노테이션을 추가함으로써 TTL시간이 만료되면 이벤트가 전달되어 서버와 통신하게 된다. 이후 관련된 주키와 관련된 보조키들을 전부 삭제시켜준다.
    • (해당 어노테이션을 추가했을때 해당 엔티티로 SAVE를 할때에 어떠한 Key가 하나더 생겨나는데 아마 이 Key가 서버와의 재통신을 통해서 관련된 키를 전부 삭제시켜주는것으로 예상된다.)

 

4. 앞선 과정들을 마치고 나는 K8S 서버에 내 스프링프로젝트와 다른 k8s 서버에 존재하는 Redis를 연동해 배포를 하려고 했다. 이때 커다란 이슈가 발생했다..

문제 상황

  • Redis를 k8s서버에 올린 후 서버를 시작하면 err unknown command config, with args beginning with: get, notify-keyspace-events 에러가 발생

해결 과정

  1. 처음에는 @EnableRedisRepositories(enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.*ON_STARTUP*, keyspaceNotificationsConfigParameter = "") 를 config 설정에 추가해주어 서버가 실행될때 notifications의 기본설정을 처리 했으나 실패했다.
  2. AUTH 관련 에러가 존재하기에 비밀번호 권한 문제라고 생각
@Bean
    fun redisConnectionFactory(): RedisConnectionFactory {
        val redisConfiguration = RedisStandaloneConfiguration()
        redisConfiguration.hostName = host
        redisConfiguration.port = port
        redisConfiguration.setPassword(password)
        return LettuceConnectionFactory(redisConfiguration)
    }
  • 위와같은 설정을 RedisConfig에 추가, password만 설정했을 경우에는 Unable connection redis 에러가 발생했다. host와 port는 yaml에 설정되어있길래 괜찮을거라 생각했는데 관련 포트와 호스트는 함께 있어야 하는것 같다. host와 port를 못찾는 상황이 발생해서 같이 추가함

 

  1. 위의 설정들을 마친 뒤에도 문제 상황과 동일한 에러가 발생
    1. /etc/redis/redis.conf 에 위치한 redis 설정에서 notify-keyspace-events "AKE” 로 변경하여 모든 이벤트에 대한 알림을 허용했음
    2. 위의 설정을 변경한후 redis server restart를 한 뒤 다시 배포한 결과 드디어 성공적인 배포를했다.

로컬의 Redis(7버전)는 notify-keyspace-events 가 자동으로 변경되어 설정되는것으로 확인했는데 k8s의 redis는 6버전이라 그런지 몰라도 notifications에 대한 설정을 따로 해줬어야 했다.. AUTH password 에 관한 설정은 yaml에서 읽지 못하고 config에서는 읽는것 같다.(이 또한 의문이였다..)

 

결론

  • 덕분에 redis.conf에 대한 다양한 설정들을 정독할 수 있었다. 말 그대로 정말 모든 설정을 하나하나 꼼꼼히 읽어보고 변경해보며 배포서버와 로컬에서 적용했다. 하지만 결국 처음에 눈에 들어온 notify-keyspace-events가 문제였다..
  • k8s의 Redis와 local의 Redis.conf 설정이 다른 것을 늦게 확인할 수 있었다. 하지만 로컬의 Redis는 자동으로 서버와 통신할때 notify-keyspace-events가 동일하게 ""으로 되어있다가 "gEx"으로 변경되는 것을 마지막즈음에 확인하였다. 왜 K8S에 올려놓은 Redis는 자동으로 변경이 되지 않는것인지 모르겠지만.. 예상으로는 6버전과 로컬이 7버전이여서 버전문제일까 싶었다.
  • 하지만 위와 같은 삽질덕에 직접 redis.conf의 설정 또한 변경해보며 이것저것 테스트 할 수 있었다. 앞으로는 에러를 좀 더 꼼꼼히 보고 근본적인 원인을 파악하기 위해 노력해야겠다.

'Redis' 카테고리의 다른 글

Redis 정의 및 사용법 && Docker 배포시 이슈  (1) 2023.07.21