redisson 의 이해 와 사용-호출 절차
20005 단어 redis
0 코드 예제
//
Config config = new Config();
config.useSingleServer().setAddress("localhost:6379").setConnectionPoolSize(5);
Redisson redisson = Redisson.create(config);
// list
List strList = redisson.getList("strList");
strList.clear(); //
strList.add(" 1");
strList.add("test2");
redisson.shutdown();
코드 로 볼 때 기본 적 인 사용 은 매우 간단 하고 마지막 사용 에서 볼 수 있다.redisson 과 접촉 하 는 것 을 제외 하고(각종 데이터 구 조 를 얻 음)redis 와 의 정보 연결 을 전혀 느끼 지 못 합 니 다.심지어 상층 으로 돌아 가 하층 의 실현 을 고려 하지 않 아 도 되 고 모든 것 을 redisson 이 포장 했다.
1 초기 연결 구조 만 들 기
1.1 설정 정보 config
config 정 보 는 4 가지 서로 다른 연결 설정 과 다른 속성 으로 조합 되 어 있 습 니 다.다음 과 같 습 니 다.
private SentinelServersConfig sentinelServersConfig;// server
private MasterSlaveServersConfig masterSlaveServersConfig;//
private SingleServerConfig singleServerConfig;//
private ClusterServersConfig clusterServersConfig;//
// , , ( )
private int threads = 0; // 0 = current_processors_amount * 2
private RedissonCodec codec;// ( object->byte[], byte[]->object) , jackson
위의 4 가지 config 에 대해 같은 계승 체 계 를 바탕 으로 다음 과 같다.
위 에서 보 듯 이 baseConfig 에서 기본 적 인 속성 을 정의 한 다음 에 하나의 기계 설정 을 제외 하고 다른 것 은 모두 하나의 주종 적 인 설정 을 바탕 으로 다 중 노드 주소 와 유사 한 설정 정 보 를 기반 으로 합 니 다.뒤의 실현 에서 우 리 는 이런 디자인,즉 계승 을 통 해 다양한 장면 의 실현 을 완성 하 는 것 을 더 많이 볼 수 있 을 것 이다.
그리고 Redisson.create 를 통 해 client 와 유사 한 생 성 을 완성 합 니 다.생 성 대상 은 하나의 예 라 고 볼 수 있 습 니 다.뒤의 호출 에서 이 인 스 턴 스 를 사용 하면 됩 니 다.그 내부 구 조 는 다음 과 같다.
public class Redisson implements RedissonClient {
private final ConnectionManager connectionManager;
private final Config config;
}
그 중에서 config 는 방금 우리 가 정의 한 설정 대상 이 고 connection Manager 는 아까 의 서로 다른 유형의 연결 설정 을 통 해 서로 다른 연결 관리 자 를 실현 한 것 으로 이해 할 수 있 습 니 다.설정 정보 와 일치 하고 상대 적 인 연결 관리자 도 계승 체계 에 따라 이 루어 진 것 입 니 다.다음 과 같 습 니 다.
위의 실현 은 설정 과 일치 하지만 여 기 는 주종 관리의 기본 적 인 실현 을 채택 하고 다른 실현 은 override 에 해당 하 는 방법 을 통 해 서로 다른 하위 실현 을 제공한다.이 중 단기 실현 은 slaver 의 연결 처리 가 없 는 것 으로 이해 할 수 있다.연결 관리 자 는 연결 정보 관리 체 제 를 실현 하고 적당 한 연결 대상 을 선택 하여 서로 다른 조작 을 수행 하 는 의 미 를 실현 했다.즉,connection 호출 을 외부 로 밀봉 하고 입 구 는 connection Manager 를 통 해 처리 합 니 다.redisson 이 외부 에 제공 하 는 것 은 데이터 구조의 의미 이기 때문에 connection 정 보 를 노출 할 필요 가 없 기 때문에 이러한 실현 은 가치 가 있다.
connection Manager 의 정 의 는 다음 과 같 습 니 다.
// ,
<V> V get(Future<V> future);
/** --------------------- , start -------------- */
<V, R> R read(String key, SyncOperation<V, R> operation);
<V, R> R read(SyncOperation<V, R> operation);
<V, R> R write(String key, SyncOperation<V, R> operation);
<V, R> R write(SyncOperation<V, R> operation);
<V, R> R write(String key, AsyncOperation<V, R> asyncOperation);
<V, R> R write(AsyncOperation<V, R> asyncOperation);
<V, T> Future<T> writeAllAsync(AsyncOperation<V, T> asyncOperation);
<V, T> T read(String key, AsyncOperation<V, T> asyncOperation);
<V, T> T read(AsyncOperation<V, T> asyncOperation);
/** --------------------- , end -------------- */
/** --------------------- , future start -------------- */
<V, T> Future<T> readAsync(String key, AsyncOperation<V, T> asyncOperation);
<V, T> Future<T> readAsync(AsyncOperation<V, T> asyncOperation);
<V, T> Future<T> writeAsync(String key, AsyncOperation<V, T> asyncOperation);
<V, T> Future<T> writeAsync(AsyncOperation<V, T> asyncOperation);
/** --------------------- , future end -------------- */
/** ( ), , */
<K, V> RedisConnection<K, V> connectionReadOp(int slot);
2 데이터 연결 생 성
연결 을 만 드 는 것 은 현재 작업 이 읽 기 인지 쓰기 인지 에 따라 진 행 됩 니 다.읽 기 작업 이 라면 주종 을 통 해 기계 에서 연결 할 수 있 기 때 문 입 니 다.호스트 에서 쓰기 동작 을 만 드 는 연결 만 고려 합 니 다.그래서 우 리 는 그 에 상응하는 실현 을 직접 살 펴 본다.
protected <K, V> RedisConnection<K, V> connectionWriteOp(int slot) {
return getEntry(slot).connectionWriteOp();
}
entry,즉 masterSlaveEntry 로 전 달 됩 니 다.entry 는 하나의 기계 의 연결 설정 대상 을 구체 적 으로 표시 하 는 것 으로 이해 할 수 있 습 니 다.
public <K, V> RedisConnection<K, V> connectionWriteOp() {
// , ,
acquireMasterConnection();
// , ,
RedisConnection<K, V> conn = masterEntry.getConnections().poll();
if (conn != null) {
return conn;
}
//
conn = masterEntry.getClient().connect(codec);
......
return conn;
}
구체 적 인 connect 방법 을 보면 RedisAsyncConnection 대상 을 만 들 고 원 격 포트 에 연 결 된 channel 에 등록 하여 해당 하 는 active 이 벤트 를 통 해 channel 에 대한 연결 을 완성 합 니 다.후속 작업 은 모두 channel 에 이 벤트 를 보 내 는 것 을 통 해 이 루어 집 니 다.구체 적 인 코드 는 다음 과 같다.
connect = bootstrap.handler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(watchdog, handler, connection);
}
}).connect();
}
connect.sync();
연결 할 때 3 개의 프로세서,즉 IN OUT 프로 세 서 를 지정 한 것 을 위 에서 볼 수 있다
watchlog 는 연결 이 끊 겼 을 때 다시 연결 할 지 여 부 를 처리 합 니 다.
handler 는 최종 명령 의 바 텀 전송 과 수신 을 처리 합 니 다.
connection 은 redis 명령 에 대한 패키지 호출 을 포함 하여 명령 의 퍼 가기 를 책임 집 니 다.handler 는 네트워크 층 에서 일 하고 connection 은 응용 층 에서 일 하 는 것 으로 이해 할 수 있다.
3 호출 명령 을 보내다
3.1 보 낼 준비 작업
redissonList 의 size 작업 은 connection 의 dispatch 명령 을 호출 하여 작 동 합 니 다.다음 과 같다.
public synchronized <T> Promise<T> dispatch(CommandType type, CommandOutput<K, V, T> output, CommandArgs<K, V> args)
type 은 LLEN 과 같은 지정 한 명령 을 표시 합 니 다.
output 는 데이터 가 돌아 온 후에 commandHandler 에서 해당 하 는 결 과 를 output 에 역 정렬 하 는 것 을 나타 낸다.
args 는 명령 의 구체 적 인 매개 변 수 를 나타 낸다.
output 데이터 가 돌아 온 후에 외부 로 전 환 된 정 보 를 알려 야 하기 때문에 이에 대응 하 는 promise 가 필요 합 니 다.이것 은 listner 로 execute(connection)의 결과 반전 에 추 가 됩 니 다.
3.2 데이터 명령 전송
해당 코드 는 connection 의 dispatch 에서 주로 다음 코드 로 구성 되 어 있 습 니 다.
Command<K, V, T> cmd = new Command<K, V, T>(type, output, args, multi != null, promise);
queue.put(cmd);
channel.writeAndFlush(cmd);
그 다음 에 여기 에는 commandHander 가 구체 적 인 데이터 전송 작업 을 책임 져 야 합 니 다(채널 에 등 록 된 해당 프로세서 이기 때 문 입 니 다).구체 적 인 코드 는 다음 과 같 습 니 다.
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
Command, ?, ?> cmd = (Command, ?, ?>) msg;
ByteBuf buf = ctx.alloc().heapBuffer();
cmd.encode(buf);
ctx.write(buf, promise);
}
3.3 데이터 결과 분석
다음 작업 은 commandHandler 에서 해당 하 는 데 이 터 를 받 습 니 다.다음 과 같 습 니 다.
// channelRead decode
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer) throws InterruptedException {
while (true) {
Command cmd = queue.peek();
if (cmd == null
|| !rsm.decode(buffer, cmd.getOutput())) {
break;
}
cmd = queue.take();
cmd.complete();
}
}
여기 서 명령 을 보 낼 때 각 명령 에 해당 하 는 순 서 를 quue 에 입력 하기 때문에 결과 에 도 quue 에 대응 하 는 결과 에 따라 대응 합 니 다.여기 서 가장 먼저 나 온 결과 가 가장 먼저 나 온 cmd 에 해당 한다 고 생각 합 니 다.rsm.decode 를 통 해 해당 buffer 의 결 과 를 역 직렬 화 output 에서 마지막 으로 cmd.complete 를 호출 하여 진일보 한 promise 를 알 립 니 다.다음 과 같다.
public void complete() {
completeAmount--;
if (completeAmount == 0) {
Object res = output.get();
......
promise.setSuccess((T)res);
}
}
}
3.4 데이터 구조의 역방향 처리
이전 처리 에서 해당 cmd 의 complete 처리 에서 이전에 전 달 된 promise 는 result 가 설정 되 어 있 기 때문에 그 위 에 연 결 된 promise 도 데이터 값 을 추가 로 설정 합 니 다.만약 맨 위 에 있다 면,우 리 는 다음 과 같은 코드 를 사용 할 때:
mainPromise.awaitUninterruptibly().getNow()
최종 적 으로 해당 하 는 결 과 를 얻 을 수 있 고 그 수 치 는 최종 적 으로 업무 코드 에 나타난다.
4 netty 와 의 통합
위 에서 볼 수 있 듯 이 전체 redisson 과 netty 의 협 의 는 handler 의 개입,event Group 의 사용 등 을 포함 하여 모든 netty 체 계 를 사용 했다.그 다음 에 netty 가 promise 기능 을 제 공 했 기 때문에 여기 서도 해당 하 는 비동기 모델 을 대량으로 사용 하여 데이터 처 리 를 했다.
5 총결산
redisson 에서 각 부분 은 최신 기술 스 택 을 사 용 했 는데 자바 5 스 레 드 의미,Promise 프로 그래 밍 의 미 를 포함 하여 기술 학습 에 있어 높 은 학습 의 미 를 가진다.제 디 스에 비해 지원 하 는 특성 이 높 지 는 않 지만 일상적인 사용 에는 문제 가 없다.집합 에 대한 포장,디 코딩 처 리 는 모두 상 자 를 열 고 바로 사용 하 는 목적 을 달성 했다.jedis 에 비해 하나의 기본 적 인 redis 네트워크 실현 만 완 성 했 고 redisson 은 완전한 프레임 워 크 라 고 이해 할 수 있 으 며,jedis 는 언어 층 의 적합 을 완성 했다.그 다음으로 redisson 은 디자인 모델 과 인 코딩 에 있어 완전한 테스트 사례 가 있 고 코드 의 가 독성 도 매우 좋아 서 소스 급 학습 을 할 가치 가 있다.
프로젝트 에 netty 를 사용 했다 면 redis 를 통합 해 야 한다 면 redisson 을 사용 하 는 것 이 가장 좋 은 선택 이 고 의존 정 보 를 추가 할 필요 가 없습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Redis 해시에 대한 완벽한 가이드변경 가능하므로 필요에 따라 쉽게 변경하고 업데이트할 수 있습니다. Redis 해시는 구조가 평평하므로 JSON에서와 같이 여러 수준을 가질 수 없습니다. redis 해시의 명명 규칙은 hash:key 로 입력되므로...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.