redis로 타이머 구현하기(RedisKeyExpiredListener extends KeyExpireationEventMessageListener)

정 승 연·2024년 7월 11일
0

땅굴파는 이야기

목록 보기
6/6

Redis

Redis는 TTL(Time-To-Live) 기능을 제공하기 때문에 데이터의 만료 시간을 설정가능

그래서 서버에 저장할 refreshToken 의 만료 시간을 설정할 수 있기에 refreshToken 구현에 많이 쓰임

Redis 기본 문법

redis-cli
keys * // 전체 키 조회
keys pattern* // pattern- 인 키를 가진 값 모두
ttl {key} // 남은 유효시간 확인
set {key} {value} // Key-value 설정
127.0.0.1:6379> expire key2 30 // key2 expireTime 설정
(integer) 1
127.0.0.1:6379> keys * // key 전체 조회
1) "getErrorLogsDegreeCountMapDaily::5"
2) "key2"
3) "key1"
127.0.0.1:6379> expiretime key2 // utc unix time 으로 expireTime 리턴
(integer) 1720487611

Redis EXAT 으로 utc 로 만료 시간 설정

 redis 6.2 버전 이후부터는 EXAT 옵션이 추가되어 unix-time-seconds를 받음. 키가 만료되는 지정된 Unix 시간을 초 단위로 설정.

  • UNIX time 이란?
    • 1970-01-01 00:00:00 UTC 로 부터 누적 된 초를 계산

Redis TTL

  • 일정한 시간 동안만 데이터를 저장해야하는 경우에 해당 기능이 유용하게 사용 됨
  • 지정된 시간이 지나면 키가 자동으로 삭제되는 기능
  • 만료 시간을 설정하지 않으면 영원히 저장
  • 현재 컴퓨터 시간을 기반으로 하여 동작하기 때문에 컴퓨터 시간을 바꾸면 만료 여부 변경됨

Redis TTL 원리

  • TTL 만료 방법
    • 수동적인 만료
      • 액세스를 시도할 때 까지 키를 삭제하지 않음
      • 키를 읽을 때마다 키가 만료 되었는지 확인하고 만료된 경우 null 반환하고 삭제
      • 근데 키에 접근하지 않으면 영원히 만료되지 않음
    • 능동적인 만료
      • 주기적으로 무작위의 키를 확인하고 만료된 키가 있으면 계속 진행하며 키를 제거
      • 확률 상으로 만료된 키의 비율을 확인하고 만료된 키가 많다면 무작위로 키를 확인하고 필요에 따라 만료하는 작업을 반복한다.

Redis를 타이머로 사용하기

scheduler 로 매 시간을 탐지해 타이머를 구현하는 것. 스레드를 열어 타이머를 작동하는 것보다. redis key 만료 기능으로 서버 리소스를 줄여 타이머를 구현 할 수있지 않을까?

redis key 값 만료를 통해 spring 에서 scheduler 없이 타이머를 구현할 수 있음.

RedisKeyExpiredListener를 사용

  • rediskey 가 만료되면 listener 가 동작해 이후 로직을 수행할 수 있음
  • 특정 메시지를 갖고 있는 key 가 만료되면 onMessage 메소드를 override 하여 이에 해당하는 로직 수행 가능.

@Component
public class RedisKeyExpiredListener extends KeyExpirationEventMessageListener {

    @Autowired
    private MqttBasculeBridgeService mqttBasculeBridgeService;

    @Autowired
    private AutoGrillsService autoGrillsService;

    public RedisKeyExpiredListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {

        if (message.toString().contains("fireShutter")) {
            mqttBasculeBridgeService.fireShutterExpiredReceiver(message);
        }

        else if (message.toString().contains("autoGrill")) {
            autoGrillsService.sendMqttOnRedisKeyExpiration(message.toString());
        }

    }

}

타이머를 구현할 다른 방법이 있을까?

https://codingdog.tistory.com/entry/redis-키-값을-일정-시간이-지나면-expire-시켜-봅시다

0개의 댓글