본문 바로가기

SPRING

[Spring+Redis] 스프링과 레디스 연동

안녕하세요.

이번에는 Redis(메모리 디비)와 스프링을 연동 해보도록 하겠습니다.

레디스는 이전 포스팅과도 같이 메모리 디비이면서 NoSql이라고도 합니다.

그럼 시작,

http://projects.spring.io/spring-data-redis/

일단 여기 접속하시면 최신 라이브러리를 다운 받을 수 있습니다.

1. pom.xml

<dependency>
         <groupId>org.springframework.data</groupId>
         <artifactId>spring-data-redis</artifactId>
         <version>${redis.version}</version>
</dependency>

위에 사이트에서 받은 라이브러리 제 기준으로 1.5.1이 되겠습니다.

그리고 레디스에 접속하기 위해서는 RedisClient도 필요로 합니다.

Java에선 Jedis를 사용하겠습니다.

<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
   <version>${jedis.version}</version>
</dependency>

이 놈의 버전은 2.6.2 입니다.

 

2. Java Config

레디스 Java Config는 찾기 힘들었습니다. 거의가 xml 환경 설정으로 되 있다보니.. 그래서 xml 환경설정 보고 Java Config 만들어보았습니다. 별로 어렵지 않더군요.

@Configuration
public class RedisConfig {

 @Bean
 public JedisConnectionFactory jedisConnectionFactory() {
  
  JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
  jedisConnectionFactory.setHostName("192.168.1.10");
  jedisConnectionFactory.setPort(6379);
  jedisConnectionFactory.setTimeout(0);
  jedisConnectionFactory.setUsePool(true);
  
  return jedisConnectionFactory;
 }

 @Bean
 public StringRedisTemplate redisTemplate(JedisConnectionFactory jedisConnectionFactory) {
  StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
  stringRedisTemplate.setConnectionFactory(jedisConnectionFactory);
  return stringRedisTemplate;
 }
}

간단합니다. ConnectionFactory를 빈으로 생성해주고 생성된 Bean을 StringRedisTemplate에 주입합니다. 나중에 Service에서 사용하게 되는건 StringRedisTemplate가 되겠습니다.

3. Service

@Service("redisService")
public class RedisService {
 
 @Autowired
 private RedisTemplate<String, String> template;

 @Resource(name="redisTemplate")
 private ListOperations<String, String> listOps;
 
 @Resource(name="redisTemplate")
 private HashOperations<String, String, String> hashOps;
 
 @Resource(name="redisTemplate")
 private SetOperations<String, String> setOps;

 public List<Sensor> getSensor() {
  
  RedisOperations<String, String> redis = listOps.getOperations();
  
  Set<String> keys = redis.keys("sensor*");
  
  Iterator<String> iter = keys.iterator();
  
  List<Sensor> sensorList = new ArrayList<Sensor>();
  
  while(iter.hasNext()) {
   String key =  iter.next().toString();
   int size = (int)(long)redis.opsForList().size(key);
   for(int i=0; i<size; i++) {
    Sensor sensor = new Sensor();
    String[] value =redis.opsForList().leftPop(key).split("_");
    sensor.setDeviceName(key);
    sensor.setValue(value[0]);
    sensor.setRegTime(value[1]);
    sensor.setCate(value[2]);
    sensorList.add(sensor);
   }
  }
  return sensorList;
 }
}
설명을 하자면 @Resource를 통해서 데이터를 조회합니다.

레디스는 key value 형태이지만 여러가지 자료형이 있는데요.

자료형에 맞는 데이터를 가져오기 쉽게 어려개의 Resource로 자료형에 맞는 Opration을 구분해놓은 모습니다.

제가 작성한 예제는 List 자료형인데요.

List 자료형은 하나의 키 값에 여러개의 Value가 존재할 수 있습니다. 실제로 Keyㄹ르 조회해봐도 키는 단 하나 밖에 나오지 않습니다.

하나에 여러개의 value를 담는다는 뜻에 Hashs랑 헷갈려 하실수도 있으니 Hashs는 key field value와 같이 field를 두어서 key value를 그룹지어 줄 수 있습니다.

위의 로직은,

1. sensor* 에 해당하는 키 값은 찾겠다.

2. 키 값을 iterator를 통해 while을 구성한다.

3. 각각의 키값의 리스트를 구하기 위해 opsForList().size()를 호출한다.

4. 구한 List 사이즈 만큼 opsForList().leftPop(key)를 한다.

pop을 하게 되면 리스트에서 삭제됩니다.

 

조회는 위에 보시느 것과 같이 할 수 있습니다.

그런데!! 하시다보면 잘되는 분도 있을거고 안되는 분도 있을텐데..

저는 안되는 쪽이었어요. 물론 오류는 있을 수 있습니다.

 

최신 버전 REDIS가 1.5.1 이었습니다.

그리고 JEDIS가 2.7.2 이었습니다.

근데 REDIS 1.5.1에 JEDIS 2.7.2 not stable 하다 하더라구요.

그래서 구현된 JEDIS 버전은 2.6.2 로 구현하여 진행하였습니다.

그리고 마찬가지로 commons-pool2 2.0을 사용하셔야 ClassNotFound가 발생하지 않습니다.