-
Notifications
You must be signed in to change notification settings - Fork 2
Redis Java Sample
kimhyungkook edited this page Feb 25, 2019
·
5 revisions
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
spring:
redis:
host: my-redis-master
port: 6379
password: secretpassword
cache:
redis:
cache-null-values: false
use-key-prefix: true
type: redis # spring.cache 를 redis 로 사용하도록 선언
@Configuration
@EnableCaching
public class RedisConfig {
@Autowired
private Environment environment;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
redisConf.setHostName(environment.getProperty("spring.redis.host"));
redisConf.setPort(Integer.parseInt(environment.getProperty("spring.redis.port")));
redisConf.setPassword(RedisPassword.of(environment.getProperty("spring.redis.password")));
JedisConnectionFactory connectionFactory = new JedisConnectionFactory(redisConf);
return connectionFactory;
}
@Bean
public RedisCacheConfiguration cacheConfiguration() {
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600)) // 케쉬데이터 저장 시간
.disableCachingNullValues(); // 케쉬는 null 을 허용 안함
return cacheConfig;
}
@Bean
public RedisCacheManager cacheManager() {
RedisCacheManager rcm = RedisCacheManager.builder(redisConnectionFactory())
.cacheDefaults(cacheConfiguration())
.transactionAware()
.build();
return rcm;
}
}
설명
@EnableCaching 를 선언하여 Spring Data cache 를 사용하도록 선언한다.
Spring 의 cache 관련 Annotation을 사용하여 쉽게 구현이 가능하다.
/**
* @Cacheable 은 key 에 해당하는 cache 값이 있으면 cache 를 조회하고,
* key 에 해당하는 cache 값이 없으면 메서드 안쪽의 내용을 실행하여 결과값을 key 에 저장하는 역할을 한다.
*/
@Cacheable(value = "app", key = "#userName")
public Customer getName(String userName){
LOGGER.info("find name from jdbc {}", userName);
return customerRepository.findByUserName(userName);
}
/**
* @CachePut cache 에 저장을 한다.
*/
@CachePut(value = "app", key = "#customer.userName")
@Transactional
public Customer saveCache(Customer customer) {
return customerRepository.save(customer);
}
/**
* @CacheEvict 캐쉬를 지운다.
* 여러건을 한번에 지우고 싶을때는 아래와 같이 사용한다.
*/
@Caching(evict = {
@CacheEvict(value = "app"),
@CacheEvict(value = "app", key="#customer.userName")
})
public String deleteCacheList(Customer customer) {
return "";
}
/**
* redisTemplate 을 사용하에 redis 데이터를 직접 컨트롤을 할 수가 있다.
* redis pub/sub 을 사용할적에 메세지를 보내기 위한 Template 으로 쓰인다.
*/
@Bean
public RedisTemplate redisTemplate() {
RedisTemplate redisTemplate = new RedisTemplate<>();
// Serializer 를 등록하지 않으면 Default Serializer로 JdkSerializationRedisSerializer 를 사용하며
// 이때 모든 값은 UniCode로 되어버린다
// 출처: https://yonguri.tistory.com/entry/스프링부트-SpringBoot-개발환경-구성-3-Redis-설정 [Yorath's 블로그]
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
@Autowired
private RedisTemplate redisTemplate;
/**
* 레디스를 사용하는 방법중에 데이터 저장 공간으로 활용을 할 수가 있다.
* 이렇게 생성된 데이터는 삭제를 하기 전까지는 데이터가 남아있는다.
*/
public Customer saveNameByRedis(String userName){
Customer c = new Customer();
c.setUserName(userName);
c.setFirstName(userName);
String key = "app2::"+userName;
redisTemplate.opsForValue().set(key, c);
return c;
}
/**
* redisTemplate.opsForValue() 를 사용하여 key 에 대한 값을 조회할 수 있다.
* 조회는 list, set, hash, value 등이 있다.
*/
public Customer getNameByRedis(String userName){
String key = "app2::"+userName;
Customer value = (Customer)redisTemplate.opsForValue().get(key);
return value;
}
/**
* redisTemplate.delete 를 사용하여 데이터를 지울수 있다
* Set<String> keys = redisTemplate.keys(key); 를 통하여 여러 키를 조회하여 한번에 지울수도 있다.
*/
public String deketeKeyByRedis(String userName){
String key = "app2::"+userName;
redisTemplate.delete(key);
// delete multi keys
// String key = "app2::*"+userName+"*";
// Set<String> keys = redisTemplate.keys(key);
// redisTemplate.delete(keys);
return "ok";
}
/**
* 여러개의 key 를 조회하여 list 로 만들어 데이터를 조회하는 예제
*/
public List<Customer> getListByRedis(String userName){
// like 조회
String key = "app2::*"+userName+"*";
Set<String> keys = redisTemplate.keys(key);
List<Customer> value = (List<Customer>)redisTemplate.opsForValue().multiGet(keys);
return value;
}
/**
* 메시지 큐를 위한 Bean을 추가
*/
@Bean
MessageListenerAdapter messageListener() {
return new MessageListenerAdapter(new RedisMessageSubscriber());
}
/**
* 채널의 메세지를 주고받을수있는 컨테이너 정의
* 컨테이너는 redis 로 부터 메세지를 받고, 구독자에게 메세지를 보내는 역할
*/
@Bean
RedisMessageListenerContainer redisContainer() {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory());
container.addMessageListener(messageListener(), topic());
return container;
}
/**
* 메세지를 게시하는 bean
* RedisMessagePublisher 를 Autowired 하여 사용할수 있도록 선
*/
@Bean
RedisMessagePublisher redisPublisher() {
return new RedisMessagePublisher(redisTemplate(), topic());
}
/**
* 메세지를 주고 받을수있는 공간인 Channel 등록
*/
@Bean
ChannelTopic topic() {
return new ChannelTopic("messageQueue");
}
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private ChannelTopic topic;
public RedisMessagePublisher(RedisTemplate redisTemplate, ChannelTopic topic) {
this.redisTemplate = redisTemplate;
this.topic = topic;
}
/**
* convertAndSend() 메서드는 목적지( 채널 )에 메시지를 전달하는 역할을 합니다.
* pub sub 모델의 특징 상 채널을 구독하고 있는 모든 구독자에게 메시지가 전달됩니다.
*/
public void publish(String message) {
redisTemplate.convertAndSend(topic.getTopic(), message);
}
public static List<String> messageList = new ArrayList<String>();
/**
* pattern 을 통해 채널 매칭을 위한 패턴을 정의할수 있음
* 패턴을 정의하면 여러 채널로 부터 구독이 가능함
*/
@Override
public void onMessage(Message message, byte[] pattern) {
messageList.add(message.toString());
System.out.println("Message received: " + message.toString());
}
@RestController
@RequestMapping("/pubsub")
public class PubSubTestController {
@Autowired
RedisMessagePublisher redisMessagePublisher;
@RequestMapping(value = "/send", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public void sendMessage(@RequestParam("message") String message ) throws Exception {
redisMessagePublisher.publish(message);
}
}
메세지를 publish 하게 되면 구독하고있는 모든 Subscriber 에게 메세지가 전달된다.
Subscriber가 메시지 받는 것을 보장하지는 않는다.
## http 로 메세지 전달받는지 확인한다.
http http://localhost:8280/pubsub/send\?message\=hello
콘솔창에
Message received: hello 라고 뜬다.
## redis-cli에서 messageQueue 채널을 구독하여, 메시지가 오는지 확인
kubectl exec -it my-redis-master-0 -- redis-cli -a secretpassword
> pubsub channels : 채널 목록을 확인
messageQueue
> subscribe messageQueue : messageQueue 채널을 구독
hello