redisson 의 이해 와 사용-호출 절차

20005 단어 redis
redisson 은 redis 를 연결 하 는 자바 클 라 이언 트 작업 입 니 다.jedis 에 비해 비동기 모델 을 사용 하여 netty promise 프로 그래 밍 을 대량으로 사용 하 는 클 라 이언 트 프레임 워 크 입 니 다.
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 을 사용 하 는 것 이 가장 좋 은 선택 이 고 의존 정 보 를 추가 할 필요 가 없습니다.

좋은 웹페이지 즐겨찾기