3 min to read
Redis란
실무 관점에서의 Redis
Redis란?
- REmote DIctionary Server의 약자
- Key-Value 기반의 인메모리 데이터 저장소
- jvm위에서 동작하지 않고 어떠한 데이터도 캐싱할 수 있음. 따라서 GC 대상이 되지 않아 오버헤드도 줄어듦.
redis cache 사용 조건
- 단순한, 또는 단순한 구조의 정보를 다룰 때
- 데이터를 반복적으로 동일하게 제공해야 할 때
- 데이터의 변경 주기가 빈번하지 않고, 데이터의 단위 처리 시간이 오래 걸릴 때
- 데이터의 업데이트가 반드시 최신 상태로 유지될 필요가 없을 때
이 중 2가지만 만족해도 캐시 적용을 검토해봄 직 하다.
어노테이션
@Cacheable
- 결과 값을 캐시에 저장. 그 후에 같은 메소드가 호출 될 때는 메소드가 실행되지 않고 캐시에서 해당 값이 반환됨.
- key 설정 시, SpEL이 사용됨.
사용 조건
- spring AOP 가 적용되기 때문에 @Transactional, @Async와 마찬가지로 제약조건이 있음.
- public 메소드에서만 적용됨.
- 같은 객체 내의 메소드끼리 호출시 캐싱 처리되지 않음.
설정
- 캐시 설정 파일인 config.class 생성하여 해당 클래스에
@EnableCaching
어노테이션을 선언. - 캐시를 적용할 메소드에 알맞는 어노테이션을 선언.
예시 코드
- 어노테이션 설정
@Cacheable(cacheNames = KEY, key = "'personalMall:' + #p0.toString()") public PersonalMallResponse getPersonalMallResponseCache(int mallNo) { GodoMallKey godoMallKey = getMallKeyOrAdd(mallNo); PersonalMallResponse personalMallResponse = new PersonalMallResponse(); personalMallResponse.setPersonalMall(godoMallKey.isPersonalMall()); personalMallResponse.setPersonalMallChangedStatus(godoMallKey.getPersonalMallChangedStatus()); return personalMallResponse; }
- redisTemplate 설정 코드와 비교
public PersonalMallResponse getPersonalMallResponseCache(int mallNo) { String key = KEY + Integer.toString(mallNo); String value = (String)redisTemplate.opsForValue().get(key); final PersonalMallResponse personalMallResponses = JacksonUtils.toModelSafely(value, PersonalMallResponse.class); if (ObjectUtils.isEmpty(personalMallResponses)) { value = JacksonUtils.toForceJson(getMallKeyOrAdd(mallNo)); redisTemplate.opsForValue().set(key, value, EXPIRE_TIME, EXPIRE_TIME_UNIT); return JacksonUtils.toModelSafely(value, PersonalMallResponse.class); } else { return personalMallResponses; } }
@CacheEvict
캐시를 제거하고자 할 때 원하는 메소드에 선언
- ex.
@Transactional @CacheEvict(cacheNames = KEY, key = "'personalMall:' + #mallNo.toString()") public void setChangedPersonalMallStatus(int mallNo, PersonalMallChangedStatus personalMallChangedStatus) { // redisTemplate.delete(KEY + Integer.toString(mallNo)); GodoMallKey godoMallKey = getMallKeyOrAdd(mallNo); godoMallKey.setPersonalMallChangedStatus(personalMallChangedStatus); }
@CachePut
캐시를 갱신하고자 할 때 선언
설정
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setDefaultSerializer(new JdkSerializationRedisSerializer());
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new JdkSerializationRedisSerializer());
template.afterPropertiesSet();
setConnectionFactory
레디스 커넥션 팩토리 설정한다.
setDefaultSerializer
기본 직렬화 방식을 설정한다.
setKeySerializer
key-value에서 key부분의 serializer를 설정한다.
setHashKeySerializer
hashkey 또는 field의 serializer를 설정한다.
setValueSerializer
key-value에서 value부분의 serializer를 설정한다.
afterPropertiesSet
디폴트 serializer를 설정해준다.
Serializer 종류
JdkSerializationRedisSerializer
디폴트 serializer로 설정된 serializer가 없으면 해당 serializer가 default로 설정된다. 기본적인 자바 직렬화 방식으로 serializer가 적용된다.
StringRedisSerializer
JacksonJsonRedisSerializer
json 형태로 저장된다.
Jackson2JsonRedisSerializer
json 형태로 저장된다.
GenericToStringSerializer
설정된 타입으로 변환된다.
template.setValueSerializer(new GenericToStringSerializer<>(Integer.class));
GenericJackson2JsonRedisSerializer
StringRedisTemplate vs RedisTemplate
StringRedisTemplate
- type : String
- 문자열에 특화된 redis 제공
- RedisTemplate를 상속받은 클래스.
- new StringRedisSerializer()로 직렬화함.
public class StringRedisTemplate extends RedisTemplate<String, String> { public StringRedisTemplate() { RedisSerializer<String> stringSerializer = new StringRedisSerializer(); setKeySerializer(stringSerializer); setValueSerializer(stringSerializer); setHashKeySerializer(stringSerializer); setHashValueSerializer(stringSerializer); } public StringRedisTemplate(RedisConnectionFactory connectionFactory) { this(); setConnectionFactory(connectionFactory); afterPropertiesSet(); } protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) { return new DefaultStringRedisConnection(connection); } }
RedisTemplate
- type : Map<Key, Value>
- 아래 5가지 데이터 타입의 interface를 제공
- ValueOperation : string
- ListOperation : list
- SetOperation : set
- ZSetOperation : sorted
- HashOperation : hash
- 특징
- thread-safe. 재사용 가능
- 데이터 타입 별 operation
- string : opsForValue() ``` public void setValue(String key, String value) { redisTemplate.opsForValue().set(key, value); }
public String getValue(String key, String value) { return redisTemplate.opsForValue().get(key, value); }
- list : opsForList()
public Long addToListFromRight(String key, String value) { redisTemplate.opsForList().rightPush(key, value); } public Long addToListFromLeft(String key, String value) { redisTemplate.opsForList().leftPush(key, value); } public List
getList(String key, String value) { return redisTemplate.opsForList().range(key, 0, -1); } - set : opsForSet()
public boolean addSet(String key, String value) { redisTemplate.opsForSet().add(key, value); } public Set
getSet(String key, String value) { return redisTemplate.opsForSet().member(key); } ``` - zset : opsForZSet()
- hash : opsForHash()
참고
- https://yonguri.tistory.com/82
- https://055055.tistory.com/m/75?category=852871
- https://supawer0728.github.io/2018/04/18/spring-cache-fallback/
Comments