[SPRING] 봄 데이터 Redis 만료 키
SPRING봄 데이터 Redis 만료 키
나는 하나의 Spring Hibernate Application을 가지고있다. 내 응용 프로그램에서는 최근 스프링 데이터 Redis 구현됩니다.
spring-servlet.xml
<!-- redis connection factory -->
<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true"/>
<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnFactory"/>
그리고이 RedisTemplate은 ServiceImpl 클래스에서 사용됩니다.
RedisServiceImpl
@Autowired
private RedisTemplate<String, T> redisTemplate;
public RedisTemplate<String, T> getRedisTemplate() {
return redisTemplate;
}
public void setRedisTemplate(RedisTemplate<String, T> redisTemplate) {
this.redisTemplate = redisTemplate;
}
이제 redisServer에 데이터를 추가했습니다.
public void putData(String uniqueKey, String key, Object results) {
redisTemplate.opsForHash().put(uniqueKey, key, results);
}
이제 Expire 키를 제거하고 싶습니다.
나는 구글에서 검색하지만, 구글에서 모두 이런 말을하고있다.
redisTemplate.expire(key, timeout, TimeUnit);
이 만료 메서드에서는 key 대신 uniqueKey를 제공해야합니다. 하지만 uniqueKey 대신 Expire 키가 필요합니다.
그래서 만료 키를 위해 무엇을 도와 주시겠습니까?
해결법
-
==============================
1.Redis 버전 3.2.100을 사용하고 있습니다.
Redis 버전 3.2.100을 사용하고 있습니다.
redis 템플릿 대신 Use Redis Cache Manager를 사용하고 redistemplate를 cacheManager에 전달하고 set expires 속성을 사용하여 기본적으로 String & Long 맵을 생성합니다. 캐시 이름을 추가하고 만료 시간 (TTL)을 설정할 수 있습니다.
cacheManager의 setDefaultExpiration 메소드를 사용하여 모든 캐시에 동일한 만료 시간을 설정할 수 있습니다.
@SuppressWarnings({ "rawtypes", "unused" }) @Configuration @EnableCaching(proxyTargetClass = true, mode = AdviceMode.ASPECTJ, order = 1) @PropertySource("classpath:/application.properties") public class CacheConfigImpl extends CachingConfigurerSupport { private @Value("${redis.ip}") String redisHost; private @Value("${redis.port}") int redisPort; private static final Map<String, Long> cacheMap = new HashMap<String, Long>(); static { cacheMap.put("method1cache", 600L); cacheMap.put("method2cache", 600L); cacheMap.put("method3cache", 800L); } @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } @Bean public JedisConnectionFactory redisConnectionFactory() { JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory(); redisConnectionFactory.setHostName(CustomPropertyLoader.getProperty("redis.ip")); redisConnectionFactory.setPort(Integer.parseInt(CustomPropertyLoader.getProperty("redis.port"))); return redisConnectionFactory; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Bean(name = "RCacheManager") public CacheManager cacheManager(RedisTemplate redisTemplate) { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); cacheManager.setExpires(cacheMap); cacheManager.setUsePrefix(true); final String redis_client_name = CustomPropertyLoader.getProperty("redis.client.name"); cacheManager.setCachePrefix(new RedisCachePrefix() { private final RedisSerializer<String> serializer = new StringRedisSerializer(); private final String delimiter = ":"; public byte[] prefix(String cacheName) { return this.serializer .serialize(redis_client_name.concat(this.delimiter).concat(cacheName).concat(this.delimiter)); } }); return cacheManager; } }
-
==============================
2.실제로 RMapCache 객체를 사용하여 Redisson 프레임 워크 (Redis 기반 데이터 격자 for Java)로이 작업을 수행 할 수 있습니다. 맵 엔트리마다 ttl 및 maxIdle을 설정할 수있는 기능을 제공합니다. 예:
실제로 RMapCache 객체를 사용하여 Redisson 프레임 워크 (Redis 기반 데이터 격자 for Java)로이 작업을 수행 할 수 있습니다. 맵 엔트리마다 ttl 및 maxIdle을 설정할 수있는 기능을 제공합니다. 예:
// implements java.util.concurrent.ConcurrentMap interface RMapCache<String, SomeObject> map = redisson.getMapCache("anyMap"); // ttl = 10 minutes, map.put("key1", new SomeObject(), 10, TimeUnit.MINUTES); // ttl = 10 minutes, maxIdleTime = 10 seconds map.put("key1", new SomeObject(), 10, TimeUnit.MINUTES, 10, TimeUnit.SECONDS);
-
==============================
3.실제로 Redis 해시 내부의 개별 키에 대한 TTL을 만료 시키거나 설정할 수는 없습니다. 전체 해시를 만료 시키거나 TTL로 설정할 수 있습니다. 이를 지원하려면 데이터 구조를 변경해야합니다.
실제로 Redis 해시 내부의 개별 키에 대한 TTL을 만료 시키거나 설정할 수는 없습니다. 전체 해시를 만료 시키거나 TTL로 설정할 수 있습니다. 이를 지원하려면 데이터 구조를 변경해야합니다.
왜 이것이 불가능한 지에 대한 링크가 있습니다. 아래는 몇 가지 발췌 내용입니다. 레디스 만료
또한 해시 필드에서 만료를 설정할 수있는이 링크를 사용하면 데이터 구조를 변경하여 만료를 처리하는 데 도움이 될 수 있습니다.
-
==============================
4.키에 TTL을 설정하려면 cacheManager의 빈을 여러 개 만들고 개별 빈에 대해 TTL을 설정할 수 있습니다. 그런 다음 귀하의 사용에 따라 필요한 cachemanager를 사용할 수 있습니다. 여기 제가 구현 한 것이 있습니다.
키에 TTL을 설정하려면 cacheManager의 빈을 여러 개 만들고 개별 빈에 대해 TTL을 설정할 수 있습니다. 그런 다음 귀하의 사용에 따라 필요한 cachemanager를 사용할 수 있습니다. 여기 제가 구현 한 것이 있습니다.
@Configuration("cacheConfig") @EnableCaching public class CacheConfig extends CachingConfigurerSupport{ @Bean public JedisConnectionFactory redisConnectionFactory() { System.out.println("redisConnectionFactory"); JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory(); // Defaults redisConnectionFactory.setHostName("127.0.0.1"); redisConnectionFactory.setPort(6379); return redisConnectionFactory; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) { System.out.println("redisTemplate"); RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>(); redisTemplate.setConnectionFactory(cf); redisTemplate.setKeySerializer(new StringRedisSerializer()); return redisTemplate; } @Bean @Primary public CacheManager cacheManager2(RedisTemplate redisTemplate) { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); // Number of seconds before expiration. Defaults to unlimited (0) cacheManager.setDefaultExpiration(20); cacheManager.setUsePrefix(true); return cacheManager; } @Bean public CacheManager cacheManager1(RedisTemplate redisTemplate) { RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate); // Number of seconds before expiration. Defaults to unlimited (0) cacheManager.setDefaultExpiration(60); cacheManager.setUsePrefix(true); return cacheManager; } }
위에 작성한 cachemanager beans를 사용하려면,
@Cacheable(value = "users", key = "#userId.toString()", cacheManager ="cacheManager2") @RequestMapping(value = "/{userId}", method = RequestMethod.GET) public User getUser(@PathVariable String userId) { LOG.info("Getting user with ID {}.: "+userId); return userService.fetchUserDataonUsers(userId); } @Cacheable(value = "users", key = "#userId.toString()", cacheManager ="cacheManager1") @RequestMapping(value = "data/{userId}", method = RequestMethod.GET) public String getUserData(@PathVariable String userId) { LOG.info("Getting user with ID getUserData {}.: "+userId); return userService.fetchUserDataonUsers(userId).toString(); }
우리는 @Cacheable에 cacheManager = "cacheManager2"를 정의 할 때, 구성에 정의 된 cacheManager2에 대해 TTL 세트를 사용합니다. cacheManager1과 동일합니다.
-
==============================
5.이러한 목적으로 Quartz를 채택 할 수 있습니다 (Redis 레코드 용 ttl 구현). Spring Boot를 사용하면 Scheduler가 자동으로 구성됩니다. 따라서 서비스 레이어에 직접 자동으로 연결할 수 있습니다.
이러한 목적으로 Quartz를 채택 할 수 있습니다 (Redis 레코드 용 ttl 구현). Spring Boot를 사용하면 Scheduler가 자동으로 구성됩니다. 따라서 서비스 레이어에 직접 자동으로 연결할 수 있습니다.
@Autowired private Scheduler scheduler;
그런 다음 이와 같은 작업을 구현해야합니다 (이 예제에서는 Spring Redis Data를 사용하고 있습니다).
@Slf4j @Component public class RemoveExpiredRecordJob implements Job { @Autowired public RedisRepository redisRepository; @Override public void execute(JobExecutionContext jobExecutionContext) { String key = jobExecutionContext .getJobDetail() .getKey() .getName(); redisRepository.deleteById(key); log.info("Record removed due timeout :: {}", key); }
}
그런 다음 JobDetail 및 Trigger를 생성하기위한 로직을 캡슐화 할 수 있습니다.
@Component public class SchedulerComponentBuilder { public JobDetail getJobDetail (String key, Class<? extends org.quartz.Job> clazz) { return JobBuilder.newJob().ofType(clazz) .storeDurably(false) .withIdentity(key) .withDescription("This key will be removed from Redis store when time expires.") .build(); } public Trigger getTrigger(int ttl, JobDetail jobDetail) { java.util.Calendar calendar = java.util.Calendar.getInstance(); calendar.add(java.util.Calendar.SECOND, ttl); return TriggerBuilder.newTrigger().forJob(jobDetail) .withDescription("This trigger fires once to remove an expired record from Redis store.") .startAt(calendar.getTime()) .build(); } }
그리고 마지막으로 Redis 저장소에 레코드를 저장 한 직후에이 레코드 (uniqueKey)를 다음과 같이 제거 할 작업을 예약해야합니다.
@Autowired private SchedulerComponentBuilder schedulerComponentBuilder; private void schedule(String uniqueKey, int ttl) { try { JobDetail jobDetail = schedulerComponentBuilder.getJobDetail(uniqueKey, RemoveExpiredRecordJob.class); Trigger jobTrigger = schedulerComponentBuilder.getTrigger(ttl, jobDetail); scheduler.scheduleJob(jobDetail,jobTrigger); log.info("Job is scheduled :: {}", jobDetail); } catch (SchedulerException e) { log.error("Filed to schedule a job {}", e); throw new RuntimeException(e); } }
from https://stackoverflow.com/questions/34893279/spring-data-redis-expire-key by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 보안 로그 아웃이 j_spring_security_logout으로 이동합니다. (0) | 2019.03.29 |
---|---|
[SPRING] 포스트 구조로 봄 콩 테스트하기 (0) | 2019.03.29 |
[SPRING] Proguard는 수업을 찾을 수 없다고 말하고 있습니다. (0) | 2019.03.29 |
[SPRING] applicationContext.xml에서 환경 변수 읽기 (0) | 2019.03.29 |
[SPRING] Scope을 기반으로 @PreAuthorize를 사용하여 스프링 보안 oauth 리소스를 보호하려면 어떻게해야합니까? (0) | 2019.03.29 |