깊이 Jedis(소스 코드)

8249 단어
깊이 Jedis(소스 코드)
https://blog.huachao.me/2016/2/%E6%B7%B1%E5%85%A5Jedis/?utm_source=tuicool&utm_medium=referral
Redis 클라이언트와 서버 측의 통신 프로토콜은 이렇게 간단하다

RESP 프로토콜


RESP(Redis Serialization Protocol)는 redis 서버와 redis client의 통신 프로토콜입니다.
  • TCP Port 6379
  • Request-Response 모델.2개의 예외, 1)pipeline;2)pub/sub
  • 5가지 DataType, Simple String(+);Errors(-);Integers(:);Bulk String($);Arrays(*)
  • \r
    (CRLF)는 끝 문자
  • Simple String 예: "+OK\r
    "
  • Errors 예: -WRONGTYPE Operation against a key holding the wrong kind of value
  • Integer 예: ":1000\r
    "
  • Bulk String 예: "$6\r
    foobar\r
    "
    6은 뒤에 6개의byte 길이가 있음을 나타낸다
  • Null 예: "$-1\r
    "
  • Arrays의 예: "*2\r
    $3\r
    foo\r
    $3\r
    bar\r
    "
    2는 2개의 원소가 있음을 나타낸다."*0\r
    "
    공수조
  • 를 나타낸다
  • 클라이언트가 Bulk String으로 명령을 보냅니다.예: llen mylist -> *2\r
    $4\r
    llen\r
    $6\r
    mylist\r
  • redis 서버가 RESP DataType 에 응답합니다.예: :48293\r
  • RESP 프로토콜에 대한 Jedis의 추상

  • Protocol은 상기 RESP 프로토콜을 실현하는 주요 클래스입니다. 그 중에서 sendCommand(final RedisOutputStream os, final byte[] command, final byte[]... args) 프로토콜 연결 문자열에 따라 redis 서버에 보내는 방법, Object read(final RedisInputStream is) 어떻게 redis 서버의 반환을 받고 Java Object로 변환하는지 볼 수 있습니다.
  • BinaryXxxCommands <- BinaryJedis, XxxCommands <- Jedis 바이너리 흐름을 통해 보내는 모든 Redis 명령을 추상화하는 데 사용
  • XxxCommands <- JedisClusterCommands와 유사한 명령을 추상적으로 추상적으로 사용하는 것은 결국 모두 2진 흐름이다. Binary를 없애면 작가가 싫증을 내는 것으로 추정된다.잘못된 점은 가르침을 주십시오.
  • Commands, Connection <- BinaryClient <- Client는 네트워크 송신 명령과 수신 회답을 추상화하였으며, 그 중에서 클라이언트는 매개 변수인encode를byte[]로 하고 BinaryClient를 호출하는 방법을 사용한다.BinaryClient에서 Connection#sendCommand 호출;sendCommand는 connect()를 호출하여 RedisInputStream과 RedisOutputStream을 프로토콜로 구성합니다.sendCommand에서 명령 보내기;client.getXxxReply () 는 먼저 outputstream의 내용flush를 내보낸 다음 Protocol을 호출합니다.read는 수신된 반환 값을 처리합니다.
    /*   Connection.java */
    protected Connection sendCommand(final ProtocolCommand cmd, final byte[]... args) {
    try {
    connect();
    Protocol.sendCommand(outputStream, cmd, args);
    pipelinedCommands++;
    return this;
    } catch (JedisConnectionException ex) {
    // Any other exceptions related to connection?
    broken = true;
    throw ex;
    }
    }

    public void connect() {
    if (!isConnected()) {
    try {
    socket = new Socket();
    // ->@wjw_add
    socket.setReuseAddress(true);
    socket.setKeepAlive(true); // Will monitor the TCP connection is
    // valid
    socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to
    // ensure timely delivery of data
    socket.setSoLinger(true, 0); // Control calls close () method,
    // the underlying socket is closed
    // immediately
    // <-@wjw_add

    socket.connect(new InetSocketAddress(host, port), connectionTimeout);
    socket.setSoTimeout(soTimeout);
    outputStream = new RedisOutputStream(socket.getOutputStream());
    inputStream = new RedisInputStream(socket.getInputStream());
    } catch (IOException ex) {
    broken = true;
    throw new JedisConnectionException(ex);
    }
    }
    }

    /* */
    public String getBulkReply() {
    final byte[] result = getBinaryBulkReply();
    if (null != result) {
    return SafeEncoder.encode(result);
    } else {
    return null;
    }
    }

    public byte[] getBinaryBulkReply() {
    flush();
    pipelinedCommands--;
    return (byte[]) readProtocolWithCheckingBroken();
    }

    protected Object readProtocolWithCheckingBroken() {
    try {
    return Protocol.read(inputStream);
    } catch (JedisConnectionException exc) {
    broken = true;
    throw exc;
    }
    }

  • Jedis는 Pipeline이라는 클래스를 통해 Redis의 pipeline을 추상화하고 jedis.pipelined()Pipeline 실례를 되돌려준다. 그리고 이 Pipeline 실례의client는 현재 jedis 실례의client이다.pipeline.a_redis_command()를 호출할 때 하나responseList가 있습니다. 각각command가 대응하는response를 기록하는 데 사용됩니다.pipeline.syncAndReturnAll()client.getAll() 모든command를 한 번flush() 내보내고 List 를 가져와서 이 Object를responseList에 채웁니다.

    Jedis 사용 고려사항

  • Jedis instance 자체가 안전하지 않아요!제디스풀을 써야 돼요.
    // JedisPool spring 
    JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");

    Jedis jedis = null;
    try {
    jedis = pool.getResource();
    /// ... do stuff here ... for example
    jedis.set("foo", "bar");
    String foobar = jedis.get("foo");
    jedis.zadd("sose", 0, "car"); jedis.zadd("sose", 0, "bike");
    Set<String> sose = jedis.zrange("sose", 0, -1);
    } finally {
    if (jedis != null) {
    jedis.close();
    }
    }
    /// ... when closing your application:
    pool.destroy();

  • JedisPool은 하나의 포장 모델로 내부는 Apache Common Pool2이고 Pool 안에 Jedis가 들어 있다.제디스가 라인 보안이 아닌 이유는 제디스 클래스의fields(client,pipeline,transaction)가 동기화되지 않았기 때문이다.만약thread마다 Jedis 실례가 하나 있다면, 사실 라인 안전 문제도 존재하지 않는다. 바로 사용 완료에 주의해야 한다jedis.close().JedisPool은 DBCP의 Pool과 마찬가지로 Jedis 실례를 만들고 라인에 제공하는 것입니다. Pool 기술은 IDLE로 표시된 Jedis를 복원하여 메모리 이용률을 제공하고 비용을 줄일 수 있습니다.

  • 작은 매듭

  • Redis의 통신 프로토콜은 간단하고 쉽습니다
  • Jedis가 프로토콜을 실현할 때 사용하는 Client는 Connection과Command를 결합시키고 규칙에 맞고 배울 만하다
  • JedisPool은 Apache Common Pool로 ThreadSafe
  • 를 만들었습니다.
  • 좋은 웹페이지 즐겨찾기