-
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 ๋ก ์ฌ์ฉํ๋๋ก ์ ์ธ
bean ์ ๋ฑ๋กํ๋ ํ์ผ์ ์๋์ฒ๋ผ ๋ฐ๋ก Config ํ์ผ์ ์์ฑํ์ฌ ๋ง๋๋๊ฒ ์ข๋ค.
@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์ ์ฌ์ฉํ์ฌ ์ง์ key ์ ์ ๋ ฅ์ ์ํจ๋ค.
/**
* 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;
}
redis ๋ฅผ ๋ฉ์ธ์ง pub/sub ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํด์๋ MessageListener ์ publisher ๋ฅผ ๋ฑ๋กํด์ผํ๋ค.
/**
* ๋ฉ์์ง ํ๋ฅผ ์ํ 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