whithdrawal에 id가 담긴다!

하지만 public class Withdrawal에 설정해준 것으로 3분 이후에 삭제되어야 하는 users table의 user 정보(colum)이 삭제되지 않고 있는데…
private static final String WITHDRAWAL_KEY_PREFIX = "withdrawal:";
@Id
private String id;
@TimeToLive
private Long expiration; // TTL 설정
public Withdrawal(String id) {
this.id = id;
this.expiration = 3L * 60; // 3분 동안 유지
}
문제점
Withdrawal 엔티티를 생성할 때는 TTL을 설정하지만, 이 TTL은 데이터를 저장하는 데 사용되지 않고 있음UserService - public ResponseEntity withdrawUser(Long id, User user)
Withdrawal 클래스는 Redis에 데이터를 저장하고 해당 데이터의 만료 시간을 설정하기 위한 클래스
만료시간을 public class UserService에 만드나요? public class Withdrawal에 만드나요?
Withdrawal 클래스 내에서 만료 시간을 설정하는 방법입니다. 이 방법을 선택하면 Withdrawal 객체가 Redis에 저장될 때 TTL이 함께 설정됩니다. 이 방법을 사용하려면 @TimeToLive 어노테이션을 사용하고, 객체 생성 시 TTL 값을 설정해야 합니다. 예를 들어, this.expiration = 300L;로 설정하여 5분(300초) 동안 유지할 수 있습니다.withdrawalRepository.save() 메서드를 호출할 때 TTL을 설정하는 방법입니다. 이 방법을 선택하면 저장할 때 TTL을 유동적으로 설정할 수 있으므로, 다양한 TTL 설정이 필요한 경우에 유용합니다. 예를 들어, withdrawalRepository.save(withdrawal, Duration.ofMinutes(3));와 같이 TTL을 설정할 수 있습니다.Repository에 직접 설정
@Repository
public class WithdrawalRepository {
private static final String WITHDRAWAL_KEY_PREFIX = "withdrawal:";
@Autowired
private RedisTemplate<String, Withdrawal> redisTemplate;
public void save(Withdrawal withdrawal, Duration duration) {
String key = WITHDRAWAL_KEY_PREFIX + withdrawal.getId();
redisTemplate.opsForValue().set(key, withdrawal, duration);
}
// 나머지 리포지토리 메서드 및 로직
}
위의 코드에서 RedisTemplate을 사용하여 TTL을 직접 설정하고 opsForValue().set() 메서드를 사용하여 객체를 Redis에 저장하고 있습니다. Duration 객체를 사용하여 TTL을 설정하고, 이렇게 설정된 TTL이 지나면 Redis에서 해당 객체가 자동으로 삭제됩니다.
만약 Withdrawal 엔티티를 저장할 때마다 TTL을 설정해야 하는 경우에는 이와 같은 방식으로 직접 설정해야 합니다. 이렇게 하면 withdrawalRepository.save(withdrawal, Duration.ofMinutes(3));을 사용하여 TTL을 설정할 수 있습니다.RedisHash에 직접 설정
package com.sparta.seoulmate.entity.redishash;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.TimeToLive;
@RedisHash(value = "withdrawal")
@Getter
@AllArgsConstructor
public class Withdrawal {
private static final String WITHDRAWAL_KEY_PREFIX = "withdrawal:";
@Id
private String userId;
@TimeToLive
private Long expiration; // TTL 설정
// 생성자에서 userId 초기화
public Withdrawal(String userId) {
this.userId = userId;
this.expiration = 180L; // 3분 동안 유지 (3분 * 60초)
}
}
whithdrawal에 id가 담기는데 설정해준 시간이 되도 whithdrawal redis에 담긴 user id나 users table에 있는user 정보(Colum)이 삭제가 되지 않는다….
지정한 시간이 지나도 삭제가 되지 않는 문제!
package com.sparta.seoulmate.entity.redishash;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.TimeToLive;
@RedisHash(value = "withdrawal")
@Getter
@AllArgsConstructor
public class Withdrawal {
private static final String WITHDRAWAL_KEY_PREFIX = "withdrawal:";
@Id
private String userId;
@TimeToLive
private Long expiration; // TTL 설정
public Withdrawal(String userId) {
this.userId = userId;
this.expiration = 180L; // 3분 동안 유지 (3분 * 60초)
}
}package com.sparta.seoulmate.entity.redishash;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
@RedisHash(value = "withdrawal", timeToLive = 20)
@Getter
public class Withdrawal {
private static final String WITHDRAWAL_KEY_PREFIX = "withdrawal:";
@Id
private String userId;
public Withdrawal(String userId) {
this.userId = userId;
}
}하지만… withdrawal가 바로 삭제되지 않고 복사(?)되어 삭제되는 문제!
private static final String WITHDRAWAL_KEY_PREFIX = "withdrawal:"; 로직 삭제

복사되는 것보다는 은 key-value로 저장하는데….
참고
Redis에 만료 기간을 설정해주고 어떤 User의 정보를 삭제할 지 정해주고(탈퇴 신청) 만료되면 UserRepository에서 User 정보가 삭제되는 것 → Redis에 만료 기간을 설정해주고 어떤 User의 정보를 Redis에 옮기면서 UserRepository에서는 삭제되고 Redis에 남아 있는 어떤 User의 정보를 만료 기간이 지나면 삭제하는 것으로 바꾸기…?!
전자 방법으로 하려면 이벤트 설정이 필요하다구…
@EnableRedisRepositories를 통해 Redis 리포지토리를 활성화하고 Redis 연결 및 리스너를 구성할 수 있습니다.MessageListenerAdapter를 설정하여 Redis 만료 메시지를 리스너와 연결합니다.Redis를 연결해야 함!!
오류…
java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.sparta.seoulmate.entity.redishash.Withdrawal]
com.sparta.seoulmate.entity.redishash.Withdrawal 클래스가 직렬화 가능한(Serializable) 형태로 구현되어 있지 않아서 발생Withdrawal 클래스는 이러한 직렬화를 지원하지 않고 있다!클래스 내부에서 사용하는 모든 멤버 변수 또한 직렬화 가능해야 하기 때문에 해당 변수도 Serializable 인터페이스를 구현
import java.io.Serializable;
public class Withdrawal implements Serializable
스케줄러 어노테이션을 쓰면 레디스를 쓰지 않아도 된다…
redis에 만료기간을 설정해도 따로 떨어져 있는 users table의 user 정보는 삭제되지 않을 것이다……
→ users table(userRepository)에 담긴 user 정보를 redis로 옮기고 users table(userRepository)에 담긴 user 정보는 삭제하고 redis로 옮겨진 users의 정보에 만료기간을 두고 삭제를 시킨다…!
- 정리
1. 사용자 정보를 Redis로 이동: 사용자 정보를 처음에는 userRepository (users table)에 저장하고, 동시에 해당 정보를 Redis에도 저장합니다. 이때 Redis에 저장된 데이터에 만료 기간을 설정합니다. 이렇게 하면 Redis에서 만료 기간이 지난 데이터는 자동으로 삭제됩니다.
2. 사용자 정보 업데이트: 사용자 정보가 업데이트될 때마다, userRepository와 Redis의 해당 사용자 정보를 동기화합니다. 즉, 사용자 정보가 업데이트될 때 userRepository와 Redis의 데이터를 모두 업데이트합니다.
3. Redis를 주기적으로 정리: 만료 기간이 지난 데이터가 Redis에 남아있을 수 있으므로, 주기적으로 Redis를 확인하여 만료된 데이터를 삭제하는 작업을 수행할 수 있습니다. 이 작업은 스케줄러를 사용하여 구현할 수 있습니다.
4. Redis의 데이터를 먼저 검색: 사용자 정보를 읽어올 때, 먼저 Redis에서 해당 정보를 찾고, Redis에 없을 경우 userRepository에서 정보를 가져옵니다. 이렇게 하면 Redis에 데이터가 존재하면 데이터베이스 쿼리를 줄일 수 있습니다.
이러한 방식을 사용하면 Redis를 사용하여 데이터의 만료를 관리하고, 데이터베이스와 Redis 간의 동기화를 유지할 수 있습니다. Redis를 캐시나 데이터베이스의 확장 기능으로 사용하는 경우에 특히 유용합니다.
회원 탈퇴 신청을 한 유저의 정보를 withdrawal로 옮겨주고 옮겨주는 동시에 user table에서 그 유저의 정보를 삭제
타임투리브(만료시간만!) 이벤트 발생을 위해 → 퍼블리시, 섭스크립 매커니즘 사용해야함..
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-09-05T20:15:56.183+09:00 ERROR 18676 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 11 of constructor in com.sparta.seoulmate.service.UserService required a bean of type 'org.springframework.data.redis.core.RedisTemplate' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.data.redis.core.RedisTemplate' in your configuration.
Process finished with exit code 1private final RedisTemplate<String, String> redisTemplate;private final RedisTemplate<String, String> redisTemplate;private final UserService userService;private final RedisMessagePublisher redisMessagePublisher;user1이 회원 탈퇴 신청을 하면 withdrawal redis에 user1의 정보가 담기면서 users에 있는 user1의 정보는 삭제되고 만료기간 1분을 설정해주고 1분의 기간이 지나고 만료되면 withdrawal redis에 담긴 user1이 자동 삭제되기….
withdrawal에 정보가 담김

users table에서 11번의 user 정보가 삭제된 것을 확인

시간이 지난 후(1분 맞아..?) withdrawal:11에 있었던 정보가 사라져있는 것을 확인

UserService에 삭제 로직 때문에 삭제 되는 것이었음….
// user 테이블에서 사용자 정보 삭제
userRepository.delete(user);