jedis는 사실상 java 기반 응용프로그램 표준 드라이버이고 많이 사용함에도 Spring에서 lettuce를 선호하는 점은 다음과 같다.

여러 쓰레드에서 단일 jedis 인스턴스를 공유하려 할때 jedis쓰레드에 안전하지 않다. 멀티쓰레드환경에서 고려해야할 상황이 따른다.

안전한 방법은 pooling(Thread-pool)과 같은 jedis-pool을 사용하는 것이지만 물리적인 비용의(connection인스턴스를 미리 만들어놓고 대기하는 연결비용의 증가) 증가가 따른다.

반면 lettucenetty 라이브러리 위에서 구축되었고, connection 인스턴스((StatefulRedisConnection))를 여러 쓰레드에서 공유가 가능하다.(Thread-safe)

=> 혼동할 수 있는데, connection 인스턴스의 공유라는 점에서 Thread-safe를 논점을 둔 점이고 Single-Thread레디스에 데이터에 접근할 때는 또다르게 고려해야 할 점이다.



https://github.com/spring-projects/spring-session/issues/789

'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Redis Library  (2) 2018.11.17
Single Thread  (0) 2018.11.17
SpirngBoot에서 Redis 연동(Jedis)  (0) 2018.08.09
Redis 명령어  (0) 2018.08.04
Redis Pub/Sub Model  (0) 2018.07.01



자바 기준  사람들이 많이 사용하는 Redis Library는 다음과 같다.


  • Jedis
  • Lettuce
  • Redisson


...


기타 라이브러리는 아래에서 확인 가능하다.


https://redis.io/clients#java




Jedis 


- Jedis의 가장 큰 장점은 사용하기 쉽다.


https://github.com/xetorthio/jedis





Lettuce


- 레드로부터 안전한 sync 그리고 async와 reactive(Concurrent API structed Observer Pattern) 사용을 위한 클라이언트

- 또한 코덱과 파이프라인 등 고급 설정을 지원한다.

- netty 기반 라이브러리

- JAVA8 이상에서 안정화



https://github.com/lettuce-io/lettuce-core




Redisson


- Jedis나 Lettuce에 비해 사용하기 까다롭다.

- redis 명령어와 같은 low-level 메소드를 제공한다.


- 기타 자세한 특징

http://redisgate.kr/redis/clients/redisson_intro.php



https://github.com/redisson/redisson




Spring Data Redis  in Spring boot


- Redis를 마치 jpa repository를 이용하듯 인터페이스를 제공하는 스프링 모듈

- crudRepository를 지원하기 때문에 직관적이다. 

- Jedis, lettuce만 공식 지원,  Redisson은 현재 포함되지 않는다.





=> 주관적인 견해로 라이브러리를 선택할 때, 라이브러리 관리가 제대로 잘되고 있는지 그리고 내가 어떤 목적으로 쓸지가 중요한 것 같다.










'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Spring 에서 lettuce가 jedis 보다 많이 사용되는 이유  (0) 2018.11.27
Single Thread  (0) 2018.11.17
SpirngBoot에서 Redis 연동(Jedis)  (0) 2018.08.09
Redis 명령어  (0) 2018.08.04
Redis Pub/Sub Model  (0) 2018.07.01

Single Thread Model

Redis는 대표적인 Single Thread Model 이다. 

이로 인해 처리가 긴 Transaction이 발생했을 때, 다른 request는 처리하지 못할 수 있다.

대표적으로 flushAll 명령어는 리스트 전체를 Scan하는 구조로 100만개 처리시 1초,1000만개 처리시 10초,  1억개는 100초가 소요된다.

이를 예방하기 위해 데이터를 전체 하나의   Collection에 넣는 것이 아닌 여러 Collection 에 나눠 처리하는 방안이 좋으며 각 Collection당 보통 10000개의 데이터를 저장한다,


다른 예로 데이터를 백업하는 경우에, 앞서 AOF(메모리 덤프 및 디스크 저장)와 RDB(매번 디스크에 Write IO) 방식이 있는 것을 살펴 봤다.

이런 경우 대량의 데이터를 처리하는 경우 성능 저하를 발생하는 또다른 요인이기 때문에, 일반적으로 Master-Slave Model로 레디스를 구성하며 Master Redis는 데이터의 처리를 담당하며 slave redis에서 백업을 진행하는 것이 좋다.


출처: http://bcho.tistory.com/829

https://www.slideshare.net/charsyam2/redis-acc?ref=http://bcho.tistory.com/829



Redis Sing Thread를 회피하기 위해 Scan 을 예로 들 수 있는데  더 자세히 알고 싶다면,  카카오 기술 블로그에 작성된 강대명 개발자의 의견을 꼭 한번 읽어 보는 것을 추천한다.

http://tech.kakao.com/2016/03/11/redis-scan/

'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Spring 에서 lettuce가 jedis 보다 많이 사용되는 이유  (0) 2018.11.27
Redis Library  (2) 2018.11.17
SpirngBoot에서 Redis 연동(Jedis)  (0) 2018.08.09
Redis 명령어  (0) 2018.08.04
Redis Pub/Sub Model  (0) 2018.07.01


Gradle


compile('org.springframework.boot:spring-boot-starter-data-redis')

compile group: 'redis.clients', name: 'jedis', version: '2.9.0'







application.properties 설정


spring.cache.type=redis

spring.redis.host = 127.0.0.1 

spring.redis.password= 

spring.redis.port=6379








RedisConfig 클래스 생성


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.example.service.redis;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
 
import redis.clients.jedis.JedisPoolConfig;
 
@Configuration
@ComponentScan("com.spring.redis")
public class RedisConfig {
 
    private @Value("${spring.redis.host}"String redisHost;
    private @Value("${spring.redis.port}"int redisPort;
    private @Value("${spring.redis.password}"String password;
 
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(30);
        jedisPoolConfig.setMinIdle(10);
        jedisPoolConfig.setTestOnBorrow(true);
        jedisPoolConfig.setTestOnReturn(true);
        return jedisPoolConfig;
    }
 
    @SuppressWarnings("deprecation")
    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(jedisPoolConfig());
        jedisConnectionFactory.setHostName(redisHost);
        jedisConnectionFactory.setPort(redisPort);
        jedisConnectionFactory.setPassword(password);
        jedisConnectionFactory.setUsePool(true);
        return jedisConnectionFactory;
    }
 
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new StringRedisSerializer());
        template.setEnableDefaultSerializer(false);
        template.setEnableTransactionSupport(true);
        return template;
    }
}
cs




Redis Client에서 가장 많이 사용되는 오픈소스는 Jedis/lettuce/Redisson  중 Jedis이다.


많이 쓴다는 것은 곧 그만큼 사용하기 쉽고 레퍼런스가 많다는 의미이다.


실제로 Jedis를 통해 손쉽게 사용할 수 있었다.


Spring에서 RedisTemplate을 통해 데이터에 엑세스할 뿐 아니라 ConnectionPool의 자원 관리 또한 알아서 해준다.


=> 실제론 JedisConnectionFactory를 통해서 수행




RedisTemplate을 통해 다음과 같은 데이터 타입을 다룰 수 있다.

String

@Resource(name="redisTemplate")
private ValueOperations<String, String> valueOperations;

Set

@Resource(name="redisTemplate")
private SetOperations<String, String> setOperations;

Sorted Set

@Resource(name="redisTemplate")
private ZSetOperations<String, String> zSetOperations;

Hashes

@Resource(name="redisTemplate")
private HashOperations<String, String, String> hashOperations;

List

@Resource(name="redisTemplate")
private ListOperations<String, String> listOperations;







'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Redis Library  (2) 2018.11.17
Single Thread  (0) 2018.11.17
Redis 명령어  (0) 2018.08.04
Redis Pub/Sub Model  (0) 2018.07.01
Java에서 Redis 연동 테스트 (jedis)  (0) 2018.07.01


Command


Redis Client Too인 rdm이나,  CLI에서 관련 명령어를 수행하려면 https://redis.io/commands 에서 확인해보자.



ex)  저장된 키 값을 모두 지울 때 flushall

'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Single Thread  (0) 2018.11.17
SpirngBoot에서 Redis 연동(Jedis)  (0) 2018.08.09
Redis Pub/Sub Model  (0) 2018.07.01
Java에서 Redis 연동 테스트 (jedis)  (0) 2018.07.01
MacOS에서 Redis 설치 및 실행  (0) 2018.07.01

Pub/Sub Model


Redis는 JMS나 IBM MQ 같은 메시징에 활용할 수 있는데 1:1 형태의 Queue뿐만 아니라 1:N 형태의 Publish/Subscribe 메시징도 지원한다(Publish/Subscribe 구조에서 사용되는 Queue를 일반적으로 Topic이라고 한다). 하나의 클라이언트가 메시지를 Publish하면 이 Topic에 연결되어 있는 다수의 클라이언트가 메시지를 받을 수 있는 구조이다(Publish/Subscribe 형태의 메시징에 대해서는 http://en.wikipedia.org/wiki/ Pub/sub를 참고하길 바란다).

재미있는 것 중에 하나는 일반적인 Pub/Sub 시스템의 경우 Subscribe하는 하나의 Topic에서만 Subscribe하는데 반해, Redis에서는 pattern matching을 통해 다수의 Topic에서 메시지를 Subscribe할 수 있다. 예를 들어 topic 이름이 music.pop, music.classic이라는 2개의 Topic이 있을 때, “PSUBSCRIBE music.*”라고 하면 2개의 Topic에서 동시에 메시지를 Subscribe할 수 있다.




출처: https://www.kdata.or.kr/info/info_04_view.html?field=&keyword=&type=techreport&page=38&dbnum=176019&mode=detail&type=techreport

'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

SpirngBoot에서 Redis 연동(Jedis)  (0) 2018.08.09
Redis 명령어  (0) 2018.08.04
Java에서 Redis 연동 테스트 (jedis)  (0) 2018.07.01
MacOS에서 Redis 설치 및 실행  (0) 2018.07.01
Redis 특징(3) - Redis Persistance  (0) 2018.06.29

Jedis


Java에서 Jedis Library를 사용하여 Redis에 연동한다.



https://mvnrepository.com/artifact/redis.clients/jedis/2.9.0








Connection Pool 및 set, get, 만료시간 지정



단순 테스트 용도라면 그냥 접근해도 좋지만, 성능을 염두하고 있다면 JedisPool을 사용해야 하며 Apache-common library도 함께 필요하다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
 
public class Main {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        String host = "127.0.0.1";
        int port = 6379;
        int timeout = 3000;
        int db = 0;
        
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        
        JedisPool pool = new JedisPool(jedisPoolConfig,host,port,timeout,null,db);
        
        Jedis jedis = pool.getResource();
        
        //Connect 체크 
        System.out.println(jedis.isConnected());
        
jedis.set("key4""6");
        jedis.set("key5""6");
        
        // 데이터의 만료시간을 지정
        jedis.expire("key5",1);
        
        System.out.println(jedis.get("key5"));
        
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(jedis.get("key5"));
    
        if( jedis != null ){
            jedis.close();
        }
        pool.close();
        
    }
 
}
 
cs



>>true

>>6

>>null









list, hashes, set, sorted set 사용



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
 
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
 
public class Main {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
 
        String host = "127.0.0.1";
        int port = 6379;
        int timeout = 3000;
        int db = 2;
 
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
 
        JedisPool pool = new JedisPool(jedisPoolConfig, host, port, timeout, null, db);
 
        Jedis jedis = pool.getResource();
 
        // list 형태로 입력
        jedis.lpush("id""choi");
        jedis.lpush("id""keach");
        jedis.lpush("id""hoo");
 
        // 첫번 째 요소를 제거하고 꺼냄
        System.out.println(jedis.lpop("id"));
        // 마지막 요소를 제거하고 꺼냄
        System.out.println(jedis.rpop("id"));
 
        // hash 형태로 입력
        Map<StringString> score = new HashMap<>();
        score.put("kim""220");
        score.put("park""240");
 
        jedis.hmset("score", score);
 
        Map<StringString> getMap = jedis.hgetAll("score");
 
        Set<String> key = getMap.keySet();
 
        Iterator<String> keyIter = key.iterator();
 
        while (keyIter.hasNext()) {
            System.out.println(getMap.get(keyIter.next()));
        }
 
        // Set 형태로 입력
        jedis.sadd("user""user00");
        jedis.sadd("user""user01");
        jedis.sadd("user""user02");
 
        Set<String> user = jedis.smembers("user");
 
        Iterator<String> iter = user.iterator();
 
        while (iter.hasNext()) {
            System.out.println(iter.next());
        }
        
        
        // Sorted Set 형태로 입력
        jedis.zadd("sortedUser"1000"user00");
        jedis.zadd("sortedUser"1048"user01");
        jedis.zadd("sortedUser"1024"user02");
        
 
        if (jedis != null) {
            jedis.close();
        }
        pool.close();
 
    }
 
}
 
cs





특이하게 봐야 할 곳이 있다면 SortedUser 키 . 

user02의 경우 마지막에 추가했지만 확인해보면 가중치 값으로 인해 중간에 삽입된 것을 확인 할 수 있다.






마지막으로 키 삭제에 대한 코드는 다음과 같다.


jedis.del("key");







참고

http://jdm.kr/blog/202




'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Redis 명령어  (0) 2018.08.04
Redis Pub/Sub Model  (0) 2018.07.01
MacOS에서 Redis 설치 및 실행  (0) 2018.07.01
Redis 특징(3) - Redis Persistance  (0) 2018.06.29
Redis 특징 (2) - 지원 데이터 타입  (0) 2018.06.29

MacOS에서 Redis 설치


mac에서는 설치유틸리티인 brew를 통해 손쉽게 redis를 설치할 수 있다.




Redis 설치


$brew install redis





Redis 서비스 실행, 중지, 재시작


$brew services start redis

$brew services stop redis

$brew services restart redis



Redis 설정


# Accept connections on the specified port, default is 6379.

# If port 0 is specified Redis will not listen on a TCP socket.
port  6379   [포트번호 변경]

# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
requirepass password  [주석제거하고 패스워드 입력]

# By default Redis listens for connections from all the network interfaces
# available on the server. It is possible to listen to just one or multiple
# interfaces using the "bind" configuration directive, followed by one or
# more IP addresses.
#
# Examples:
#

# bind 192.168.1.100 10.0.0.1  
bind 127.0.0.1 192.168.0.101   [외부에서 접근 가능하도록 IP 추가 가능]





Redis 실행


$redis-server







Redis 클라이언트


https://redisdesktop.com 에서 클라이언트를 다운받고 쉽게 redis를 사용할 수 있다.




설치


ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null ; brew install caskroom/cask/brew-cask 2> /dev/null



brew cask install rdm






'Cloud & NoSQL & Middleware > Redis' 카테고리의 다른 글

Redis Pub/Sub Model  (0) 2018.07.01
Java에서 Redis 연동 테스트 (jedis)  (0) 2018.07.01
Redis 특징(3) - Redis Persistance  (0) 2018.06.29
Redis 특징 (2) - 지원 데이터 타입  (0) 2018.06.29
Redis 특징  (2) 2018.06.29

+ Recent posts