Spring Boot Redis (standard)
2020/01/10 - [NoSQL/Redis] - Redis 특징
2020/01/10 - [NoSQL/Redis] - Docker Redis
2020/01/10 - [NoSQL/Redis] - Spring Boot Redis (standard)
2020/01/10 - [NoSQL/Redis] - Redis install linux
2020/01/10 - [NoSQL/Redis] - Redis Replication (Master Slave) 구성
2020/01/10 - [NoSQL/Redis] - Redis Sentinel 구성
2020/01/10 - [NoSQL/Redis] - Redis Clustering 구성
2020/01/13 - [NoSQL/Redis] - Spring boot redis Sentinel Config
2020/01/13 - [NoSQL/Redis] - spring boot redis clustering config
Spring Boot Redis
1. Spring boot 설정
1.1 application.yml 설정
spring:
devtools:
restart:
enabled: false
datasource:
url: jdbc:mysql://{IP}:3306/audience?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Seoul
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: password
hikari:
pool-name: hikari-cp
minimum-idle: 5
maximum-pool-size: 200
idle-timeout: 10000
connection-timeout: 10000
validation-timeout: 10000
max-lifetime: 580000
data-source-properties:
cachePrepStmts: true
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
useServerPrepStmts: true
jpa:
generate-ddl: true
open-in-view: true
show-sql: false
hibernate:
ddl-auto: validate
naming:
physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
database: mysql
database-platform: org.hibernate.dialect.MySQL5Dialect
properties:
hibernate.jdbc.batch_size: 50
hibernate.jdbc.batch_versioned_data: true
hibernate.order_inserts: true
hibernate.order_updates: true
hibernate.enable_lazy_load_no_trans: true
hibernate.format_sql: true
data:
jpa:
repositories:
enabled: true
redis:
port: 6379
host: {IP}
- 프로젝트의 설정파일이 길지만 필요한건 redis 설정만 사용해도 무방하다.
1.2 RedisConfiguration 설정
기본적으로 yaml 에서 설정에 설정후 redis Operation 을 @Resource Annotation을 사용하여 Inject 한 Template을 Optional 하게 사용 한다. 여기서는 Custom Configuration 을 사용한다.
@Configuration
@EnableRedisRepositories // -> Redis Repository 활성화
public class RedisConfiguration {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
/**
* Netty 기반 ConnectionFactory
* @return
*/
@Bean
public RedisConnectionFactory redisConnectionFactory(){
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisHost,redisPort);
// 패스워드가 있는경우
//lettuceConnectionFactory.setPassword("");
return lettuceConnectionFactory;
}
@Bean
public RedisTemplate<String,Object> redisTemplate(){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(this.redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
//redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(UserEntity.class)); // <- 주고 받을 데이터(Entity)를 미리 설정 할때
return redisTemplate;
}
}
네티기반 오픈 소스 커넥터 LettuceConnectionFactory 와 jedis 의 JedisConnectionFactory 커넥터 가 있으며 커넥터는 둘중 하나를 골라서 적절한 커넥터를 구성한다.
RestTemplate Bean 설정
RestTemplate 을 사용하여 저장할때 와 setValueSerializer 의 직렬화 정보를 지정해주게 되는데, 직렬화 하지않으면 기본적으로 Byte로 저장하기 대문에 출력시 바이트 문자열이 출력되는걸 볼수 있다. 이에 setValueSerializer 는 new StringRedisSerializer()로 직열화 해준다. setKeySerializer 키에 직렬화 해주지않으면 이것도 byte 코드로 저장됨으로 주의. JSON 으로 직렬화 하여 사용 하기도 하며, 좀더 가볍하 하기 하기 위해 message pack 을 사용하기도 한다.
Redis Sentinel 은 Lettuce 를 통해서만 사용 할 수 있다.
1.3 RedisTemplate 사용한 Repository
미리정의한 restTemplate 을 @Resource Annotation을 사용하여 주입 받아 사용 한다.
ValueOperations, hashOperations, setOperations
@Repository
public class AudienceRepository {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Resource(name = "redisTemplate")
ValueOperations<String, String> valueOperations;
@Resource(name = "redisTemplate")
HashOperations<String, String, String> hashOperations;
@Resource(name = "redisTemplate")
SetOperations<String,String> setOperations;
public void save(String key, String data) {
valueOperations.set(key, data);
}
public void saveHashType(String key, String hashKey, String value) {
redisTemplate.opsForHash().put(key, hashKey, value);
//hashOperations.put(key, hashKey, value);
}
public void saveSetType(String key, String... value) {
//redisTemplate.opsForSet().add(key, value);
setOperations.add(key,value);
}
public Object find(String key) {
return redisTemplate.opsForValue().get(key);
}
public Boolean delete(String key) {
return redisTemplate.delete(key);
}
}
1.4 Spring Data 를 이용한 interface Repository
- Spring redis data 사용 @RedisHash @Id 를 사용한 도메인 엔티티 구성 @id로 식별자 송성 지정 @RedisHash 해시 유지
@RedisHash("user")
@ToString
@Getter@Setter
public class UserEntity implements Serializable {
@Id
private String id;
private String name;
private int age;
}
- 엔티티를 유지하기 위한 기본 저장소 인터페이스 구성
public interface TestRedisRepository extends CrudRepository<UserEntity, String> {
}
1.5 테스트 코드 작성
- 1.5.1 Test code - RestTemplate
@SpringBootTest
@DisplayName("AudienceRepository info demo")
@Slf4j
class AudienceRepositoryTest {
@Autowired
AudienceRepository audienceRepository;
@Test
void save() {
audienceRepository.save("5","test 5");
}
@Test
void find() {
String data = (String) audienceRepository.find("1");
log.info("redis string data = {}", data);
}
@Test
void delete() {
audienceRepository.delete("5");
}
@Test
void saveHashType() {
audienceRepository.saveHashType("test:hash:user","name","cj");
audienceRepository.saveHashType("test:hash:user","age","100");
}
@Test
void saveSetType() {
audienceRepository.saveSetType("test:user:set:hobby","책");
audienceRepository.saveSetType("test:user:set:hobby","책1","책2");
}
}
- 1.5.2 Test code - spring data redis
@SpringBootTest
@DisplayName("Test info demo")
@Slf4j
class TestRedisRepositoryTest {
@Autowired
private TestRedisRepository testRedisRepository;
@Test
void testSave1() {
UserEntity userEntity = new UserEntity();
userEntity.setId("cj");
userEntity.setName("씨제이");
userEntity.setAge(100);
testRedisRepository.save(userEntity);
}
@Test
@DisplayName("Redis 데이터 조회 ")
void testFindById() {
UserEntity userEntity = testRedisRepository.findById("cj").orElseGet(UserEntity::new);
log.info("user = {}", userEntity);
}
}