관리 메뉴

ballqs 님의 블로그

[Spring] RedisTemplate vs Redisson 본문

코딩 공부/Spring

[Spring] RedisTemplate vs Redisson

ballqs 2024. 11. 22. 18:40

이전에 Redisson내용으로 작성한 글이 있습니다.

https://ballqs.tistory.com/68

해당 글에는 동시성 제어하는 방법에 관해서만 작성했는데 Redisson도 RedisTemplate와 같이 사용이 가능하다는 점을 파악했고 둘의 차이점에 관해 작성하고자 합니다.

 

RedisTemplate

장점

  • 간단한 사용법: Redis의 주요 명령어를 Java 메서드로 호출 가능.
  • 풍부한 자료구조 지원: String, Hash, List, Set, ZSet 등 다양한 Redis 자료구조를 다룰 수 있음.
  • Spring과의 강력한 통합: Spring Cache, Spring Session 등과 쉽게 연계 가능.
  • 유연성: 커스터마이징을 통해 RedisSerializer 설정 등 다양한 방식으로 활용 가능.

단점

  • 분산 락 지원 부족: RedisTemplate 자체로는 분산 락 기능을 제공하지 않음.
  • 사용 난이도: 복잡한 Redis 스크립트나 고급 기능(예: Pub/Sub)을 구현하려면 추가 작업 필요.
  • 비동기 지원 제한적: 기본적으로 동기 방식으로 동작하며, 비동기 작업은 직접 구현해야 함.

 

String 데이터 처리

@Service
public class StringService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void useString() {
        redisTemplate.opsForValue().set("key1", "value1"); // 데이터 저장
        String value = redisTemplate.opsForValue().get("key1"); // 데이터 읽기
        System.out.println("Value for key1: " + value);
    }
}

 

Hash

@Service
public class HashService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public void useHash() {
        redisTemplate.opsForHash().put("user:1", "name", "Alice");
        redisTemplate.opsForHash().put("user:1", "age", 25);

        Object name = redisTemplate.opsForHash().get("user:1", "name");
        System.out.println("User name: " + name);

        Map<Object, Object> user = redisTemplate.opsForHash().entries("user:1");
        System.out.println("User details: " + user);
    }
}

 

List

@Service
public class ListService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void useList() {
        redisTemplate.opsForList().rightPush("myList", "value1");
        redisTemplate.opsForList().rightPush("myList", "value2");

        String value = redisTemplate.opsForList().leftPop("myList"); // 왼쪽에서 데이터 가져오기
        System.out.println("Popped value: " + value);

        List<String> allValues = redisTemplate.opsForList().range("myList", 0, -1);
        System.out.println("All List Values: " + allValues);
    }
}

 

Set

@Service
public class SetService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void useSet() {
        redisTemplate.opsForSet().add("mySet", "value1", "value2", "value3");
        Set<String> values = redisTemplate.opsForSet().members("mySet");
        System.out.println("Set Values: " + values);

        redisTemplate.opsForSet().remove("mySet", "value1");
        System.out.println("Updated Set: " + redisTemplate.opsForSet().members("mySet"));
    }
}

 

Sorted Set

@Service
public class SortedSetService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void useSortedSet() {
        redisTemplate.opsForZSet().add("mySortedSet", "Alice", 10.5);
        redisTemplate.opsForZSet().add("mySortedSet", "Bob", 20.0);

        Set<String> range = redisTemplate.opsForZSet().range("mySortedSet", 0, -1);
        System.out.println("Sorted Set Values: " + range);

        redisTemplate.opsForZSet().remove("mySortedSet", "Alice");
        System.out.println("After Removal: " + redisTemplate.opsForZSet().range("mySortedSet", 0, -1));
    }
}

 

Redisson

장점

  • 분산 락 및 동기화 지원: RLock, RReadWriteLock, RSemaphore 등 분산 환경에서의 동시성 제어 기능 제공.
  • Rich Objects: RMap, RList, RQueue 등 Redis 자료구조를 Java 컬렉션처럼 사용할 수 있음.
  • 비동기 및 반응형 지원: 비동기(CompletableFuture) 및 Reactive 방식 지원.
  • 편리한 Pub/Sub: Pub/Sub 기능을 손쉽게 구현 가능.

단점

  • 의존성 추가: 별도의 외부 라이브러리로 추가 의존성이 필요함.
  • 상대적으로 무거움: RedisTemplate에 비해 메모리와 리소스 사용량이 많을 수 있음.
  • Spring 통합 부족: Spring과의 통합이 RedisTemplate만큼 매끄럽지는 않음.

 

Redisson 자료구조

RMap (Redis Hash)

Redis의 Hash 자료구조를 Java의 Map처럼 사용합니다.

@Service
public class MapService {

    @Autowired
    private RedissonClient redissonClient;

    public void useRMap() {
        RMap<String, String> map = redissonClient.getMap("myMap");
        map.put("key1", "value1");
        String value = map.get("key1");
        System.out.println("Value: " + value);
    }
}

 

RList (Redis List)

Redis List 자료구조를 Java의 List처럼 사용합니다.

@Service
public class ListService {

    @Autowired
    private RedissonClient redissonClient;

    public void useRList() {
        RList<String> list = redissonClient.getList("myList");
        list.add("item1");
        list.add("item2");
        System.out.println("List: " + list);
    }
}

 

RSet (Redis Set)

Redis의 Set 자료구조를 Java의 Set처럼 사용합니다.

@Service
public class SetService {

    @Autowired
    private RedissonClient redissonClient;

    public void useRSet() {
        RSet<String> set = redissonClient.getSet("mySet");
        set.add("item1");
        set.add("item2");
        System.out.println("Set: " + set);
    }
}

 

RQueue (Redis Queue)

Redis의 List를 큐처럼 사용합니다.

@Service
public class QueueService {

    @Autowired
    private RedissonClient redissonClient;

    public void useRQueue() {
        RQueue<String> queue = redissonClient.getQueue("myQueue");
        queue.add("item1");
        queue.add("item2");

        String item = queue.poll(); // 큐의 첫 번째 항목을 가져오고 제거
        System.out.println("Polled item: " + item);
    }
}

 

RAtomicLong

Redis의 원자적 숫자 자료구조를 제공

여러 클라이언트 간 원자적으로 값을 증가/감소

@Service
public class AtomicLongService {

    @Autowired
    private RedissonClient redissonClient;

    public void useAtomicLong() {
        RAtomicLong atomicLong = redissonClient.getAtomicLong("myAtomicLong");
        long value = atomicLong.incrementAndGet(); // 현재 값에 1을 더하고 반환
        System.out.println("Atomic Long Value: " + value);
    }
}

 

RSortedSet

Java의 SortedSet처럼 사용 가능

값이 자동으로 정렬되어 저장

 

 

@Service
public class SortedSetService {

    @Autowired
    private RedissonClient redissonClient;

    public void useRSortedSet() {
        RSortedSet<String> sortedSet = redissonClient.getSortedSet("mySortedSet");
        sortedSet.add("item1", 1.0); // 점수 1.0을 가진 item1 추가
        sortedSet.add("item2", 2.0); // 점수 2.0을 가진 item2 추가

        System.out.println("Sorted Set: " + sortedSet);
    }
}

 

RSetMultimap

하나의 키에 여러 값을 매핑 가능

Java의 Multimap처럼 동작

@Service
public class SetMultimapService {

    @Autowired
    private RedissonClient redissonClient;

    public void useRSetMultimap() {
        RSetMultimap<String, String> multimap = redissonClient.getSetMultimap("mySetMultimap");
        multimap.put("key1", "value1");
        multimap.put("key1", "value2"); // 같은 키에 여러 값 추가 가능

        System.out.println("Values for key1: " + multimap.get("key1"));
    }
}

 

RBlockingQueue

RBlockingQueue는 블로킹 큐로, 큐가 비어있을 때 소비자가 대기하도록 만들 수 있습니다. 이는 생산자-소비자 패턴을 구현하는 데 유용합니다.

@Service
public class BlockingQueueService {

    @Autowired
    private RedissonClient redissonClient;

    // 생산자 메서드
    public void producer() {
        RBlockingQueue<String> blockingQueue = redissonClient.getBlockingQueue("myBlockingQueue");

        // 큐에 아이템 추가
        for (int i = 0; i < 10; i++) {
            String item = "item-" + i;
            blockingQueue.offer(item);
            System.out.println("Produced: " + item);
        }
    }

    // 소비자 메서드
    public void consumer() {
        RBlockingQueue<String> blockingQueue = redissonClient.getBlockingQueue("myBlockingQueue");

        try {
            for (int i = 0; i < 10; i++) {
                // 큐에서 아이템을 가져오고, 대기할 수 있음
                String item = blockingQueue.poll(10, TimeUnit.SECONDS); // 10초 대기 후 가져오기
                if (item != null) {
                    System.out.println("Consumed: " + item);
                } else {
                    System.out.println("No item consumed within the timeout.");
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("Consumer was interrupted.");
        }
    }
}

 

RSemaphore

 

 

리소스 접근 제한 제어

Java의 Semaphore와 동일한 개념

@Service
public class SemaphoreService {

    @Autowired
    private RedissonClient redissonClient;

    public void useRSemaphore() {
        RSemaphore semaphore = redissonClient.getSemaphore("mySemaphore");
        semaphore.trySetPermits(5); // 최대 5개의 접근 허용

        // 접근 시도
        if (semaphore.tryAcquire()) {
            try {
                System.out.println("Semaphore acquired!");
                // 임계 구역 코드
            } finally {
                semaphore.release(); // 세마포어 해제
                System.out.println("Semaphore released!");
            }
        } else {
            System.out.println("Could not acquire semaphore.");
        }
    }
}

 

RScoreSortedSet

점수 기반으로 정렬된 데이터를 저장

Redis의 zset을 Java 객체로 다룸

 

데이터 추가

import org.redisson.api.RScoreSortedSet;
import org.redisson.api.RedissonClient;

public class SortedSetExample {
    public static void main(String[] args) {
        // RedissonClient 초기화
        RedissonConfig config = new RedissonConfig();
        RedissonClient redissonClient = config.createClient();

        // RScoreSortedSet 인스턴스 생성
        RScoreSortedSet<String> sortedSet = redissonClient.getScoreSortedSet("mySortedSet");

        // 데이터 추가
        sortedSet.add(10.5, "Alice");
        sortedSet.add(15.2, "Bob");
        sortedSet.add(7.3, "Charlie");

        System.out.println("SortedSet Size: " + sortedSet.size()); // 출력: 3
    }
}

 

데이터 검색 및 업데이트

// 점수를 기준으로 데이터 검색
Double aliceScore = sortedSet.getScore("Alice");
System.out.println("Alice's Score: " + aliceScore); // 출력: 10.5

// 점수 업데이트
sortedSet.add(20.0, "Alice"); // 기존 점수는 덮어쓰기 됨
System.out.println("Alice's New Score: " + sortedSet.getScore("Alice")); // 출력: 20.0

 

범위 기반 검색

// 점수 범위로 데이터 검색
System.out.println("Entries between 5.0 and 15.0: " +
        sortedSet.valueRange(5.0, true, 15.0, true)); // 출력: [Charlie, Alice]

 

데이터 삭제

// 특정 값 삭제
sortedSet.remove("Charlie");

// 점수 범위로 삭제
sortedSet.removeRangeByScore(10.0, true, 25.0, true); // 점수가 10.0~25.0인 값 삭제

System.out.println("SortedSet Size after deletion: " + sortedSet.size());

 

Redisson 자료구조

자료구조 설명 Java 대응 자료구조
RMap Redis Hash를 Java Map처럼 사용 Map
RList Redis List를 Java List처럼 사용 List
RSet Redis Set을 Java Set처럼 사용 Set
RScoreSortedSet Redis Sorted Set (ZSet) SortedSet
RQueue Redis Queue를 Java Queue처럼 사용 Queue
RLock 분산 락 구현 -
RSemaphore Redis 기반 세마포어 구현 -
RReadWriteLock Redis 기반 읽기/쓰기 락 구현 -
RAtomicLong Redis 기반 원자적 숫자 연산 구현 AtomicLong
RTopic Redis Pub/Sub 구현 -

 

RedisTemplate vs Redisson 비교

항목 RedisTemplate Redisson
기능 기본적인 CRUD 및 자료구조 지원 분산 락, 고급 자료구조, 비동기 작업 지원
성능 가볍고 빠름 약간 무거울 수 있음
비동기 지원 제한적 강력한 지원
분산 락 별도 구현 필요 기본 제공 (RLock)
Spring 통합 강력한 통합 제한적
사용 난이도 간단 조금 복잡