-
@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를 만료시키기
Plan1. 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
Task2번 방안 채택
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