반응형

* Redis
- 데이터를 디스크에 쓰는 구조가 아니라 메모리에서 데이터를 처리 => 속도 빠름
- 서버 장애등으로 redis 종료 될 시 데이터 유실이 발생할 수 있음
- 한 번에 하나의 명령만 처리할 수 있음
- Redis Cluster를 사용하면 여러개의 redis를 두어 분산처리를 할 수 있음


* String, Lists, Sets, Sorted Sets, Hashes 자료 구조를 지원함
- String : 가장 일반적인 key & value 
- Sets : key & 여러 값이 들어간 value 
- Sorted Sets : 중복된 데이터를 담지 않는 Set 구조
- Lists : Array 형식의 데이터 구조

 

* Redis Cluster
여러 노드간 데이터를 자동으로 분할하는 기능 .
각기 다른 서버를 하나로 묶어 
데이터를 여러대의 장비에서 처리한다.
서버일부분이 장애가 일어나도 다른 서버의 보완을 통해 서비스를 계속 이어 나갈수 있다.

레디스  GUI 툴 

https://redis.com/redis-enterprise/redis-insight/

 

RedisInsight | The Best Redis GUI

RedisInsight provides an intuitive and efficient graphical interface for Redis, allowing you to interact with your databases and manage your data.

redis.com

 

 

Springboot 어플리케이션에서 redis 사용하기

 

1. 의존성 추가 

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

 

2. application.properties 에 redis 서버정보 추가

spring.data.redis.host=localhost
spring.data.redis.port=6379

 

3. RedisConfig.java

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

@Configuration
public class RedisConfig {

   @Value("${spring.data.redis.host}")
   private String host;

   @Value("${spring.data.redis.port}")
   private int port;

   @Value("${spring.data.redis.password}")
   private int password;

   @Bean
   public RedisConnectionFactory redisConnectionFactory() {
	RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
	redisConfiguration.setHostName(host);
	redisConfiguration.setPort(port);
	redisConfiguration.setPassword(password);
	LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisConfiguration);

       return new LettuceConnectionFactory;
   }
   
   @Primary
   @Bean
   public RedisTemplate<String, String> redisTemplate() {
       RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
       redisTemplate.setConnectionFactory(redisConnectionFactory());
       redisTemplate.setKeySerializer(new StringRedisSerializer());
       redisTemplate.setValueSerializer(new StringRedisSerializer());
       return redisTemplate;
   }

}

RedisTemplate : 트랜잭션을 지원한다. 트랜잭션으로 묶게 되면 트랜잭션 내부에서 하나의 로직이 실패하여 오류가 나는 경우 수행한 작업을 모두 취소시킨다.

 

4. RedisService.java

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;


@Service
@RequiredArgsConstructor
public class RedisService {
   private final RedisTemplate redisTemplate;


   public String getValues(String key){
       //opsForValue : Strings를 쉽게 Serialize / Deserialize 해주는 Interface
       ValueOperations<String, String> values = redisTemplate.opsForValue();
       return values.get(key);
   }



   public void setValues(String key, String value){
       ValueOperations<String, String> values = redisTemplate.opsForValue();
       values.set(key,value);
   }

   public void setSets(String key,String... values){
       redisTemplate.opsForSet().add(key,values);
   }

   public Set getSets(String key){
       return redisTemplate.opsForSet().members(key);
   }



}

 

5. RedisController.java

api를 만들어서 데이터를 넣고 요청해보었다.

import com.dominos.pilot_3.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.sql.Timestamp;
import java.util.Set;

@Controller
public class RedisController_ {
//레디스 테스트

    @Autowired
    RedisService redisService;

    @RequestMapping(value = "/redis/test/setString")
    @ResponseBody
    public void setValue(String testkey, String testvalue){
        Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis());
        redisService.setValues(testkey,testvalue);
    }

    @RequestMapping(value = "/redis/test/getString")
    @ResponseBody
    public String getValue(String testkey){
        return redisService.getValues(testkey);
    }


    @RequestMapping(value = "/redis/test/setSets")
    @ResponseBody
    public void setSets(String testkey,String... testvalues){
        redisService.setSets(testkey,testvalues);
    }

    @RequestMapping(value = "/redis/test/getSets")
    @ResponseBody
    public Set getSets(String key){
        return redisService.getSets(key);
    }

}

123123123는 Key와 123123123이라는 Value 쌍을 넣어봤다.

settest라는 Key와 ["settestvalue1","settestvalue2"] 라는 Value 쌍을 넣어봤다.

 

 

Redis Cluster를 사용하는 경우의 설정

1. application.yml

spring:
 data:
  redis:
    cluster:
      nodes:
        - xx.xx.xx.xxx:6379
        - xx.xx.xx.xxx:6380
    password: xxxxxxxxxx

 

2. RedisClusterConfigurationProperties.java

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;

@Component
@ConfigurationProperties(prefix = "spring.data.redis.cluster")
public class RedisClusterConfigurationProperties {
   List<String> nodes;

   public List<String> getNodes() {
       return nodes;
   }

   public void setNodes(List<String> nodes) {
       this.nodes = nodes;
   }

}

 

3. RedisConfig.java

import com.dominos.pilot_3.component.RedisClusterConfigurationProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableRedisRepositories
@RequiredArgsConstructor

public class RedisConfig {

   @Autowired
   RedisClusterConfigurationProperties clusterProperties;

   @Bean
   public RedisConnectionFactory redisConnectionFactory() {
       RedisClusterConfiguration redisConfig = new RedisClusterConfiguration ();
       clusterProperties.getNodes().forEach(s ->{
           String[] url = s.split(":");
           redisConfig.clusterNode(url[0],Integer.parseInt(url[1]));
       });
       redisConfig.setPassword("xxxxxxxx");
       return new LettuceConnectionFactory(redisConfig);
   }

   @Primary
   @Bean
   public RedisTemplate<String, Object> redisTemplate() {
       RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
       redisTemplate.setConnectionFactory(redisConnectionFactory());
       redisTemplate.setKeySerializer(new StringRedisSerializer());
       redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
       return redisTemplate;
   }

}

이하 데이터를 넣고 빼는 service와 controller는 동일함.

반응형

+ Recent posts