Redisson은 Redis를 기반으로 구현된 Java 인메모리 데이터 그리드(In-Memory Data Grid)입니다. 분산형 Java 표준 객체와 다양한 분산 서비스를 제공합니다. 본문에서는 Redisson을 사용하여 Redis를 조작하는 방법을 설명합니다. 사용된 소프트웨어 버전: Java 1.8.0_191, Redis 5.0.8, Redisson 3.13.2.
- 의존성 추가
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.2</version>
</dependency>
- Redisson을 이용한 Redis 조작
package com.example.redis.demo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.config.Config;
import java.io.*;
import java.util.concurrent.TimeUnit;
/**
* Redisson을 이용한 Redis 조작 예제
* Redisson은 동기 인터페이스 외에 비동기(Async), 반응형(Reactive) 및 RxJava2 표준 인터페이스를 제공합니다.
* Redisson은 Java 객체를 직렬화하여 Redis에 저장하므로, redis 명령줄로 설정된 값은 Redisson으로 가져올 때 오류가 발생할 수 있습니다.
* Redisson으로 설정된 값을 redis 명령줄로 가져오면 직렬화 관련 정보가 추가로 표시됩니다.
*/
public class RedissonOperations {
private RedissonClient client;
private RedissonReactiveClient reactiveClient;
private RedissonRxClient rxClient;
@Before
public void setup() {
Config config = new Config();
config.useSingleServer().setAddress("redis://10.49.196.10:6379").setPassword("123456");
client = Redisson.create(config);
reactiveClient = Redisson.createReactive(config);
rxClient = Redisson.createRx(config);
}
@After
public void cleanup() {
client.shutdown();
reactiveClient.shutdown();
rxClient.shutdown();
}
/**
* 범용 객체 저장소 - 모든 유형의 객체를 저장할 수 있습니다
*/
@Test
public void bucketTest() throws Exception {
// 동기 방식
RBucket<String> bucket = client.getBucket("userName");
bucket.set("zhaoyun");
System.out.println(bucket.get());
// 비동기 방식
RBucket<String> bucket2 = client.getBucket("userName2");
bucket2.setAsync("zhaoyun2").get();
bucket2.getAsync().thenAccept(System.out::println);
// 반응형 방식
RBucketReactive<String> bucket3 = reactiveClient.getBucket("userName3");
bucket3.set("zhaoyun3").block();
bucket3.get().subscribe(System.out::println);
// RxJava2 방식
RBucketRx<String> bucket4 = rxClient.getBucket("userName4");
bucket4.set("zhaoyun4").blockingGet();
bucket4.get().subscribe(System.out::println);
Thread.sleep(1000 * 5);
}
/**
* 바이너리 스트림
* InputStream 및 OutputStream 인터페이스 구현을 제공합니다
*/
@Test
public void streamTest() throws Exception {
RBinaryStream stream = client.getBinaryStream("userStream");
stream.set("zhaoyun".getBytes());
OutputStream outputStream = stream.getOutputStream();
outputStream.write("zhangfei".getBytes());
InputStream inputStream = stream.getInputStream();
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
System.out.println(result.toString());
}
@Test
public void atomicLongTest() {
RAtomicLong atomicLong = client.getAtomicLong("counter");
atomicLong.set(10);
atomicLong.incrementAndGet();
System.out.println(atomicLong);
}
/**
* 레이트 리미터(제한 장치)
*/
@Test
public void rateLimiterTest() throws InterruptedException {
RRateLimiter rateLimiter = client.getRateLimiter("apiRateLimiter");
// 초기화: 최대 처리량 - 1초에 5개 토큰
rateLimiter.trySetRate(RateType.OVERALL, 5, 1, RateIntervalUnit.SECONDS);
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
int count = 0;
@Override
public void run() {
while(true) {
rateLimiter.acquire(1);
System.out.println(Thread.currentThread() + "-" + System.currentTimeMillis() + "-" + count++);
}
}
}).start();
}
Thread.sleep(1000 * 5);
}
/**
* RList는 java.util.List 인터페이스를 구현합니다
*/
@Test
public void listTest() {
RList<String> list = client.getList("userList");
list.add("a");
list.add("zhaoyun");
list.add("zhangfei");
list.remove(1);
System.out.println(list);
}
/**
* RMap은 java.util.concurrent.ConcurrentMap 및 java.util.Map 인터페이스를 구현합니다
*/
@Test
public void mapTest() throws Exception {
RMap<String, String> map = client.getMap("userMap");
map.put("name", "zhaoyun");
map.put("location", "changshan");
map.put("camp", "shu");
map.remove("location");
map.forEach((key, value) -> {System.out.println("key=" + key + ",value=" + value);});
}
/**
* RSet은 java.util.Set 인터페이스를 구현합니다
*/
@Test
public void setTest() {
RSet<String> set = client.getSet("userSet");
set.add("zhaoyun");
set.add("zhangfei");
set.forEach(System.out::println);
}
/**
* RQueue는 java.util.Queue 인터페이스를 구현합니다
*/
@Test
public void queueTest() {
RQueue<String> queue = client.getQueue("taskQueue");
queue.add("zhaoyun");
queue.add("zhangfei");
System.out.println(queue.poll());
System.out.println(queue.poll());
}
/**
* 재진입 가능한 RLock - java.util.concurrent.locks.Lock 인터페이스를 구현합니다
*/
@Test
public void lockTest() throws InterruptedException {
RLock lock = client.getLock("resourceLock");
for (int i = 0; i < 5; i++) {
new Thread(() -> {
lock.lock();
try {
System.out.println(Thread.currentThread() + "-" + System.currentTimeMillis() + "-" + "락 획득 성공");
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
}
Thread.sleep(1000 * 5);
}
/**
* Redisson의 분산 RBitSet Java 객체는 java.util.BitSet과 유사한 구조 디자인을 사용합니다
*/
@Test
public void bitSetTest() {
RBitSet bitSet = client.getBitSet("flagBits");
bitSet.expire(5, TimeUnit.DAYS);
bitSet.set(0, true);
bitSet.set(20, true);
bitSet.set(96, true);
System.out.println(bitSet.get(10));
System.out.println(bitSet.get(20));
}
/**
* Redisson은 Redis를 사용하여 Java 분산 블룸 필터(Bloom Filter)를 구현합니다
*/
@Test
public void bloomFilterTest() {
RBloomFilter<String> bf = client.getBloomFilter("urlFilter");
if (!bf.isExists()) {
bf.tryInit(150000000L, 0.05);
bf.add("test");
bf.expire(200, TimeUnit.SECONDS);
}
bf.add("https://www.baidu.com/");
bf.add("https://www.tmall.com/");
bf.add("https://www.jd.com/");
System.out.println(bf.contains("https://www.tmall.com/"));
System.out.println(bf.count());
}
}
- Redisson 설정
package com.example.redis.config;
import org.junit.Test;
import org.redisson.Redisson;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
/**
* Redisson 설정 예제
*/
public class RedissonConfiguration {
/**
* 단일 Redis 노드 모드
*/
@Test
public void singleNodeMode() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://10.49.196.10:6379")
.setPassword("123456")
.setConnectionPoolSize(5) // 연결 풀 크기
.setConnectionMinimumIdleSize(2) // 최소 유휴 연결 수
.setDatabase(0);
RedissonClient client = Redisson.create(config);
RBucket<String> name = client.getBucket("name");
System.out.println(name.get());
}
/**
* 마스터-슬레이브 모드
*/
@Test
public void masterSlaveMode() {
Config config = new Config();
config.useMasterSlaveServers()
.setMasterAddress("redis://10.49.196.20:6379")
.addSlaveAddress("redis://10.49.196.21:6379")
.addSlaveAddress("redis://10.49.196.22:6379")
.setPassword("123456")
.setMasterConnectionPoolSize(5) // 마스터 노드 연결 풀 크기
.setMasterConnectionMinimumIdleSize(2) // 마스터 노드 최소 유휴 연결 수
.setSlaveConnectionPoolSize(5) // 슬레이브 노드 연결 풀 크기
.setSlaveConnectionMinimumIdleSize(2) // 슬레이브 노드 최소 유휴 연결 수
.setDatabase(0);
RedissonClient client = Redisson.create(config);
RBucket<String> name = client.getBucket("name");
System.out.println(name.get());
}
/**
* 센티넬 모드
*/
@Test
public void sentinelMode() {
Config config = new Config();
config.useSentinelServers()
.setMasterName("mymaster")
.addSentinelAddress("redis://10.49.196.20:26379")
.addSentinelAddress("redis://10.49.196.21:26379")
.addSentinelAddress("redis://10.49.196.22:26379")
.setPassword("123456")
.setMasterConnectionPoolSize(5) // 마스터 노드 연결 풀 크기
.setMasterConnectionMinimumIdleSize(3) // 마스터 노드 최소 유휴 연결 수
.setSlaveConnectionPoolSize(5) // 슬레이브 노드 연결 풀 크기
.setSlaveConnectionMinimumIdleSize(3) // 슬레이브 노드 최소 유휴 연결 수
.setCheckSentinelsList(false)
.setDatabase(0);
System.out.println(config.useSentinelServers().getSentinelAddresses());
RedissonClient client = Redisson.create(config);
RBucket<String> name = client.getBucket("name");
name.set("zhaoyun");
System.out.println(name.get());
}
/**
* 클러스터 모드
*/
@Test
public void clusterMode() {
Config config = new Config();
config.useClusterServers()
.setScanInterval(1000 * 2)
.addNodeAddress("redis://10.49.196.20:7000", "redis://10.49.196.20:7001")
.addNodeAddress("redis://10.49.196.21:7000", "redis://10.49.196.21:7001")
.addNodeAddress("redis://10.49.196.22:7000", "redis://10.49.196.22:7001")
.setPassword("123456")
.setMasterConnectionPoolSize(5)
.setMasterConnectionMinimumIdleSize(2)
.setSlaveConnectionPoolSize(5)
.setSlaveConnectionMinimumIdleSize(2);
RedissonClient client = Redisson.create(config);
RBucket<String> name = client.getBucket("name");
name.set("zhaoyun");
System.out.println(name.get());
}
}