ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • @RedisHash 이슈 트랙킹
    기초/JAVA 2025. 4. 1. 08:41

    Issue

    RedisHash로 저장한 키가 expired 되지않고 남아있음, 그러나 repository에서 findAll을 하게되면 null인 상황

     

    $ redis-cli MONITOR

    save

    1743129798.849147 [0 127.0.0.1:55838] "DEL" "status:2"
    1743129798.850581 [0 127.0.0.1:55838] "HMSET" "status:2" "_class" "com.test.test.Status" "status" "UNKNOWN"
    1743129798.851483 [0 127.0.0.1:55838] "SADD" "status" "2"
    1743129798.851978 [0 127.0.0.1:55838] "EXPIRE" "status:2" "60"

     

    $ CONFIG SET notify-keyspace-events Ex

    $redis-cli MONITOR

    3) "__keyevent@0__:expired"
    4) "status:2"

     

    >> set은 종료되지 않았음

     

    springboot$[repository] findAll() method

    1743130766.192815 [0 127.0.0.1:60155] "SMEMBERS" "status"
    1743130766.198055 [0 127.0.0.1:60155] "HGETALL" "status:2"

     

    >> set scan 후 하나씩 hgetall을 하고 있었음


    상황 결론

    1. @RedisHash의 경우 Hash에는 실제 객체정보가, Set에는 키가 저장됨
    2. ttl을 지정해도 @RedisHash에는 ttl설정이되지만 set에는 되지않음
    3. 만료 시 2번의 내용을 토대로 Hash는 제거되고 Set은 남아있음
    4. 따라서 findAll() 호출 시 set의 결과에서 키가 조회되고 해당 값으로 Hash를 조회하게 되면 null이 리스트로 반환되는 내용

     

    Goal 
    Hash를 만료시키기


    Plan

    1. Set키에도 expire을 추가한다. (기존 데이터는?)
    2. 기존데이터 삭제를 위해 findAll() 메소드 호출이 아닌 RedisTemplate로 findAll 메소드와 같이 scan 후 키값으로 Hash를 찾아낸다.

     

    Reference

    http://redisgate.kr/redis/clients/pdf/Spring_Data_Redis_Sets.pdf

    http://redisgate.kr/redis/clients/spring_hashes.php


    Task

    2번 방안 채택

     

    AS-IS

    @AllArgsConstructor
    public Test { 
    	RedisRepository redisRepository;
    
    	public void method() {
    		var list = redisRepository.findAll();
    		// ...
    	}
    }

     

    TO-BE

    @AllArgsConstructor
    public Test { 
    	private final StringRedisTemplate redisTemplate;
    
    	public void method() {
    		String setKey = "";
    		Objects.requireNonNull(redisTemplate.opsForSet().members(key))
                    .stream()
                    .filter(key -> Boolean.FALSE.equals(
    				redisTemplate.opsForHash().getOperations()
    					.hasKey("%s:%s".formatted(setKey, key))))
                    .forEach(key -> redisTemplate.delete("%s:%s".formatted(setKey, key)));
    	}
    }

     

     

    '기초 > JAVA' 카테고리의 다른 글

    [JAVA] Stream groupingBy  (0) 2022.09.12
    [Java] 이미지변환 HEIC 등등  (0) 2020.11.11
    자바 정규식 EUC-KR 한글 문제  (0) 2019.06.13
    [JAVA] 기초공부  (0) 2017.07.20
    [JAVA] 스레드  (0) 2017.02.09

    댓글

Designed by Tistory.