spring-data는 이름에서 느낄수 있는 그대로 데이터 접근에 필요한 기능을 제공해준다.

spring-data는 하나의 큰 카테고리로 생각할 수 있으며, 그 하위의 sub-project들은 각각 big- data, http, redis, mongoDB 등 다양한 형태로 제공되는 데이터에 접근할 수 있는 기능을 구현한다.


spring-data에서 제공되는 데이터 접근 기술은 다음과 같다.



spring-data 관련 정보는 여기서 확인하자 : http://www.springsource.org/spring-data


본 포스팅에서는 spring-data에서 redis를 사용하는 방법을 다룬다.


먼저 redis에 대해 간략한 설명은 다음과 같다.


Redis는 "REmote DIctionary System"의 약자로 메모리 기반의 Key/Value Store 이다. 
Cassandra나 HBase와 같이 NoSQL DBMS로 분류되기도 하고, memcached와 같은 In memory 솔루션으로 분리되기도 한다. 성능은 memcached에 버금가면서 다양한 데이타 구조체를 지원함으로써 Message Queue, Shared memory, Remote Dictionary 용도로도 사용될 수 있으며, 이런 이유로 인스탄트그램, 네이버 재팬의 LINE 메신져 서비스, StackOverflow,Blizzard,digg 등 여러 소셜 서비스에 널리 사용되고 있다.

BSD 라이센스 기반의 오픈 소스이며 최근 VMWare에 인수되어 계속해서 업그레이드가 되고 있다. 16,000 라인정도의 C 코드로 작성되었으며, 클라이언트 SDK로는 Action Script,C,C#,C++,Clojure,Erlang,Java,Node.js,Objective-C,Perl,PHP,Python,Smalltalk,Tcl등 대부분의 언어를 지원한다.


필자는 일반적으로 RDBMS의 SQL 질의 결과를 캐시하는 용도로서 redis를 사용하고 있으나, 위 소개글 처럼 메모리 기반 NoSQL 솔루션으로 사용될 수도 있다. 


redis에 대한 정보는 여기서 확인하자 : http://www.redis.io/clients


redis는 다양한 언어의 클라이언트를 지원한다. 우리는 java언어를 사용하기 때문에 redis 클라이언트로 jedis를 사용해야 한다.


jedis : https://github.com/xetorthio/jedis


빌드툴로 maven을 사용하고 있다면 spring-data와 jedis 설치는 다음과 같다. 

버전은 알아서 최신 버전으로 바꿔주자. (jedis는 2.0 이상 버전을 사용해야 한다.)

<!-- jedis -->
<dependency> 
    <groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.1.0</version>
</dependency> 
<!-- jedis -->

<!-- spring data for jedis -->
<dependency>
	<groupId>org.springframework.data</groupId>
  	<artifactId>spring-data-redis</artifactId>
  	<version>1.0.2.RELEASE</version>
</dependency> 
<!-- spring data for jedis -->

다음으로 spring-context에 다음과 같이 bean 설정을 추가한다. 

<!-- Redis Source -->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
	<property name="hostName" value="${redis.host}"/>
	<property name="port" value="${redis.port}"/>
	<property name="password" value="${redis.password}"/>
</bean>
    
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
   	<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<!-- Redis Source -->

위 connectionFactory 샘플에서는 가장 기본적인 host, port, password 설정만 있다.

실제는 connection pooling 사용 등 다양한 설정을 처리할 수 있음을 참고한다.


StringRedisTemplate는 RedisTemplate를 상속하는데, RedisTemplate는 spring-data에서 redis로의 데이터 접근 및 처리 명령을 제공하는 helper class이다. redis의 대부분의 연산들이 string 처리에 기반하기 때문에 StringRedisTemplate는 가장 기초적이고 빈번하게 사용된다.


redis에서는 string, hash, list, set, sorted set 자료구조를 제공하는데 spring-data에서는 각각 자료구조에 해당하는 operation을 추상화한 클래스를 제공한다.


 sting

 ValueOperations<K, V>

 list

 ListOperations<K, V>

 hash

 HashOperations<K, HK, HV>

 set  SetOperations<K, V>
 sorted set  ZSetOperations<K, V>


이들 operation 클래스 외에도 주어진 key에 operation를 바인딩한 bounnd***Ops 형태의 이름을 가지는 클래스를 제공하기 도 한다. 이들 클래스는 내부적으로 각각 자료구조에 일치하는 operation 클래스를 사용하고 있기 때문에, 실질적으로위 표에 나열된 클래스를 통해 redis 연산이 수행된다는 것이다. 


각각의 operation 클래스는 jedis에서 제공하는 명령을 그대로 wrapping 하고 있기 때문에 사용법 자체는 그리 어렵지 않다.


redis 서버가 특정 key를 포함하고 있는지 확인하는 메소드는 다음과 같다.


 Boolean RedisTemplate::hasKey(String key)


다음의 예제코드는 BoundHashOperations를 통해 redis 서버에서 hash 구조로 데이터를 저장하고 읽어오는 예이다.

BoundHashOperations은 이미 특정 key에 바인딩되어 있으므로, 데이터를 읽거나 쓸때 key를 지정하지 않는다. (여기서 말하는 key는 hash의 key가 아님. hash 데이터 자체가 바인딩된 key를 의미)

// redis서버에서 hash형태의 데이터를 읽어온다.
public void restore(BoundHashOperations<String, String, String> hashOps) {
	refKey 		 = hashOps.get("refKey");
	refName 	 = hashOps.get("refName");
	name 		 = hashOps.get("name");
	basePath 	 = hashOps.get("basePath");
	relativePath 	 = hashOps.get("relativePath");
	srcName 	 = hashOps.get("srcName");
	srcExt 		 = hashOps.get("srcExt");
	size 		 = NumberUtils.toLong(hashOps.get("size"));
	width 		 = NumberUtils.toInt(hashOps.get("width"));
	height 		 = NumberUtils.toInt(hashOps.get("height"));
	orderNum 	 = NumberUtils.toInt(hashOps.get("orderNum"));
	try { regdate = fmt.parse(hashOps.get("regdate")); } catch(Exception ignore) {/**/}
}
	
// redis서버로 hash형태의 데이터를 저장한다.
public void cache(BoundHashOperations<String, String, String> hashOps) {
	if( StringUtils.isNotEmpty(refKey) ) 		hashOps.put("refKey", refKey);
	if( StringUtils.isNotEmpty(refName) ) 		hashOps.put("refName", refName);
	if( StringUtils.isNotEmpty(name) ) 		hashOps.put("name", name);
	if( StringUtils.isNotEmpty(basePath) ) 		hashOps.put("basePath", basePath);
	if( StringUtils.isNotEmpty(relativePath) ) 	hashOps.put("relativePath", relativePath);
	if( StringUtils.isNotEmpty(srcName) ) 		hashOps.put("srcName", srcName);
	if( StringUtils.isNotEmpty(srcExt) ) 		hashOps.put("srcExt", srcExt);
	if( size != null ) 				hashOps.put("size", String.valueOf(size));
	if( width != null ) 				hashOps.put("width", String.valueOf(width));
	if( height != null ) 				hashOps.put("height", String.valueOf(height));
	if( orderNum != null ) 				hashOps.put("orderNum", String.valueOf(orderNum));
	if( regdate != null ) 				hashOps.put("regdate", fmt.format(regdate));
}		

redis에서 제공하는 list, set 등의 자료구조로의 연산도, redis에서 제공하는 명령셋을 이해하면 어렵지 않게 사용할 수 있다.


마지막으로 redis에 대한 좋은 소개글 링크를 첨부한다.


http://dev.kthcorp.com/2011/07/28/redis-buildingfast-lightweight-webapp/

'프로그래밍 > 오픈소스' 카테고리의 다른 글

spring-data에서 redis 사용하기  (0) 2012.12.06
Hibernate @NotFound 어노테이션  (0) 2012.12.05
이클립스에 GlassFish 설치하기  (0) 2011.02.17
SQLite with Eclipse  (1) 2010.05.06
SWF파일 분석 도구  (0) 2010.04.13
boost library 설치  (0) 2010.03.17
libcurl 사용하기  (0) 2010.03.15
SQLite  (3) 2009.09.11
ACE(ADAPTIVE Communication Environment)  (0) 2009.09.03
MySQL++  (0) 2009.08.21
C++ 암복호화 라이브러리 Crypto++  (0) 2009.08.20
Posted by devop

댓글을 달아 주세요