ballqs 님의 블로그
[Spring] RedisTemplate vs Redisson 본문
이전에 Redisson내용으로 작성한 글이 있습니다.
해당 글에는 동시성 제어하는 방법에 관해서만 작성했는데 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 통합 | 강력한 통합 | 제한적 |
사용 난이도 | 간단 | 조금 복잡 |
'코딩 공부 > Spring' 카테고리의 다른 글
[Spring] 웨이팅 대기열 트러블 슈팅 (3) | 2024.11.24 |
---|---|
[Spring] Spring Batch란? feat.DB 분리 작업 (0) | 2024.11.10 |
[Spring] 소나클라우드(SonaCloud)란? (0) | 2024.10.22 |
[Spring] Redis Cluster localhost에 구현하여 적용 (0) | 2024.10.15 |
[Spring] Redis 동시성 문제 Redisson으로 해결! (0) | 2024.10.08 |