redis를 사용하는 유명회사들에 대해선
redis.io 웹사이트에 다음과 같은 회사들이 언급되어 있다.
Blizzard에서 Wow 아바타 서비스에도 사용한다고 하는데 아직 확실치는 않다..
redis를 사용하는 유명회사들에 대해선
redis.io 웹사이트에 다음과 같은 회사들이 언급되어 있다.
Blizzard에서 Wow 아바타 서비스에도 사용한다고 하는데 아직 확실치는 않다..
redis를 HA로 구성했을 경우, SDR(spring-data-redis 1.4) 와 jedis커넥션을 이용한 spring과 redis 연동.
RedisSentinelConfiguration 클래스를 이용하면, HA를 지원하는 redis의 이중화 상태에서도 spring을 이용한 redis연동이 가능하다.
java코드로 연동하는 방법은 여러곳에서 나와있으므로, 본 글 에서는
xml을 이용한 DI(Dependency Injection)방식으로 spring과 HA redis를 연동하는 방식을 설명한다.
1. pom.xml 수정 (SDR , jedis를 추가)
이전글과 동일하다. 단 common-pool 대신에 이를 상속받은 JedisPoolConfig을 써봄으로 인해 common-pool은 제거.
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.5.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
2. application-config.xml 수정
2.1 네임스페이스에 xmlns:p,c, util 추가.
2.2.1 mymaster와 setntinels을 xml로 구성
2.2.2 RedisSentinelContiguration을 이용해서 HA구성.
=> SDR에 미흡한 부분이 하나 존재하여, MySentinelConfiguration 를 별도로 생성해서 이용하도록 함.
(이유는 아래 xml의 코멘트 참조)
2.2.3 jedis를 이용한 Pool과 connection구성.
이렇게만 하면 이전 예제와 동일하게 그냥 redisTemplate만을 이용해서 개발하면 자동으로 HA구성을 지원하는 개발이 된다.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Uncomment and add your base-package here:-->
<context:component-scan base-package="my"/>
<!-- myster -->
<bean id="myMaster" class= "org.springframework.data.redis.connection.RedisNode" c:host="127.0.0.1" c:port="6379" p:name="mymaster"/>
<!-- Sentinels -->
<bean id="mySent1" class= "org.springframework.data.redis.connection.RedisNode" c:host="127.0.0.1" c:port="26379"/>
<bean id="mySent2" class= "org.springframework.data.redis.connection.RedisNode" c:host="127.0.0.1" c:port="26381"/>
<bean id="mySents" class= "java.util.HashSet">
<constructor-arg>
<list>
<ref bean="mySent1" />
<ref bean="mySent2" />
</list>
</constructor-arg>
</bean>
<!-- RedisSentinelConfiguration: org.springframework.data.redis.connection.RedisSentinelConfiguration"
2.2.2 이 부분이 유일하게 아직 SDR에서 미흡한 부분이다. 이 부분은 ReidsSentinelConfiguration class 가
getter와 setter 파라미터가 다른 오류가 발생하므로, 자체 class를 하나 만들어서 해결하였다.
-->
<bean id="redisSentinelConf" class="my.MySentinelConfiguration"
p:master-ref="myMaster"
p:mySentinels-ref="mySents"
/>
<!-- p:sentinels-ref="mySents" : ERROR 발생-->
<!--2.2.3 POOL & Connection-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"/>
<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:use-pool="true"
p:poolConfig-ref="jedisPoolConfig"
c:sentinelConfig-ref="redisSentinelConf"
/>
<!--p:host-name="127.0.0.1" p:port="6379" -->
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<!-- redis template definition -->
<bean id="redisTemplate"
class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnFactory"
p:keySerializer-ref="stringRedisSerializer"
p:hashKeySerializer-ref="stringRedisSerializer"
p:valueSerializer-ref="stringRedisSerializer"/>
</beans>
3. JAVA 코드 - 유일하게 추가한 MySentinelConfiguration코드이다. 추가만 해 놓으면 된다.
- 단지, SDR의 getter와 setter의 오류를 피하기 위한 클래스이다. 향후에는 SDR에서 개선이 될 것으로 기대된다.
public class MySentinelConfiguration extends RedisSentinelConfiguration {
MySentinelConfiguration(){
super();
}
public Set<RedisNode> getMySentinels(){
Set<RedisNode> sets=super.getSentinels();
return sets;
}
public void setMySentinels( Set<RedisNode> sentinels){
super.setSentinels(sentinels);
}
}
SDR(spring-data-redis) 와 jedis커넥션을 이용한 spring을 이용한 redis 연동.
spring에서 redis를 연결하기 위한 기본적인 방법을 커넥션 위주로 설명.
실제로는 redis에 저장할 데이타 class를 별도로 만들어 serialize기능을 이용해 {key,class}형태로 저장하는 방식이 바람직하지만, 여기서는 이 부분은 생략하고 기본적인 연결과정만 설명한다.
1. pom.xml 수정 (SDR , common-pool, jedis를 추가)
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.5.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
2. application-config.xml 수정
2.1 네임스페이스에 xmlns:p 추가.
2.2 jedisConnnection, Serializer, redisTemplate 추가.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Uncomment and add your base-package here:-->
<context:component-scan base-package="my"/>
<bean id="jedisConnFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:use-pool="true" p:host-name="127.0.0.1" p:port="6379" />
<bean id="stringRedisSerializer"
class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<!-- redis template definition -->
<bean id="redisTemplate"
class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnFactory"
p:keySerializer-ref="stringRedisSerializer"
p:hashKeySerializer-ref="stringRedisSerializer"
p:valueSerializer-ref="stringRedisSerializer"/>
</beans>
이 중에서 serializer는 추가하지 않아도 동작은 잘 되지만,
기본 serializer로 동작하게 되면 redis에 데이타가 들어갈 때, 앞 부분에 xac xed x00 x05t x00 등의 character가 몇개 들어가게 된다.
(이런 이상한 캐릭터들은 standard serializer에서 사용하는 class정보이다.)
3. JAVA Service 코드
@Service
public class RedisService implements IRedisService{
@Autowired
private RedisTemplate<String,String> redisTemplate;
public Set<String> keysAll() {
//값을 넣고 싶을 땐, 이렇게..
//redisTemplate.opsForValue().set("abcKey", "valueABC");
return redisTemplate.keys("*");
}
}
redis 설치 완료 후, src 폴더로 이동해서
1. stand-alone 모드 실행.
./redis-server 로 서버실행
./redis-cli 로 client 실행.
==> stand alone 모드로 default세팅 되어 실행된다.
reds> info 하면 정보 조회가능(데이타 개수도 있음)
redis> keys * 하면 모든키 조회 가능(데이타가 많을경우는 조심)
1)"MPx_TYPE_Audiox"
2)"FS_HB"
3)"MP_TYPE_CTRL"
4)"XCOD_ROOM_x"
5)"CNFR_ROOM_x"
2. 마스터-슬레이브 모드
만약, master-slave모드로 테스트를 해보고 싶으면 redis-server를 아래명령으로 하나 더 실행한다.
$>./redis-server --port 6380 --slaveof 127.0.0.1 6379
혹시, 이 상태에서 상태를 확인해보고 싶으면 client창에서
127.0.0.1:6379> info 를 입력하면
#Replication 영역에
role:master
connected_slaves:1
임을 을 확인할 수 있다. 즉 6379서버의 slave가 잘 뜬 것이다.
3. Sentinel감시를 통한 HA 구성
위의 1,2번이 된 상태에서 아래와 같이 sentinel을 2개 정도 실행시키고....
$> src/redis-server sentinel1.conf --sentinel
$> src/redis-server sentinel2.conf --sentinel
==> 이러면 기본적인 HA완성.
이 때 1번 서버를 kill등으로 죽이면, 절체(HA)가 발생한다.
절체발생 후,
client는 새로이 아래와 같은 명령으로 접속한다. 즉 2번 서버로 접속한다.
$> redis-cli -p 6380
ㅁ 좀 더 쉽게 절체를 발생시키는 방법은
redis-cli -p 26379 로 센티널로 cli접속을 한 다음에
> sentinel failover mymaster 를 입력하면 바로 절체가 발생한다.
( http://redis.io/topics/sentinel 참조)
간단히 NO-SQL 몇 개를 초급 수준에서 비교해 보았다.
몽고DB : Java를 이용하여 서버를 개발하는 인디/소호 개발의 관점에서 볼 때 최적!
- json으로 DB에 기록을 해버리니, java개발자 입장에서는 java class가 바로 DB에 저장된다고 느낄 수 있다.
(document 저장 방식이라고 부름)
- geoSpace인덱싱이 매우 뛰어나서 혹시라도 지리적인 위치정보를 저장하는 경우, 조회에 관련된 많은 함수들이
제공되고 속도도 빠르다. 지리 시스템이라면 초 강추!
- 단점으로는 lock이 전체적으로 걸려서 write가 많은 시스템에선 비추라네요
=> (15.11월 글 참조) mongoDB3.0 부터는 wiredTiger엔진 사용시 row레벨lock(즉, document레벨락)지원.
- Replication + failOver(장애복구)기능은 존재.
- Clustering + 샤딩기능 : 존재하고, 확장(scaling or scale out)도 지원..
(참조: http://yakoola.tistory.com/57 )
Redis : 속도가 최우선인 시스템에 적합
- 메모리 DB인 만큼 속도가 최우선시 되는 시스템에서 필수로 고려해야 한다.
- 기초적인 사용법은 mySql수준이라서, 입문은 간단.
- Replication 기능은 존재하지만 Async방식이라서 cluster상에서 일부 유실이 가능한 구조이다.
- failOver기능: 원래는 없었으나, 근래에는 sentinel기능이 도입되어 안정화 단계이다.
- Clustering + 샤딩기능: 없으나 개발완료 단계이다. 올 여름 redis 3.0부터 배포가 되며, 16384개의 hash slot을
미리 나눠좋고 샤딩을 하는 방식이다. 물론 slot조정이나 이동이 가능하다.
(이전 버전에서는 clustering이 지원이 안되므로 zookeeper과 혼합해서 사용하는 방법이 혼용되었다)
Cassandra: 안정적인 시스템이며 write가 많은 초 대용량 시스템에 유리
- 읽기보다 쓰기가 더 빠르다는데 시간을 재보진 않아서 믿지는 못하고 있지만
- Clustering기능이 뛰어나 안정된 시스템이라는 인상을 많이 준다.