Redis 기초 학습 의 파이프 메커니즘 상세 분석

머리말
Redis 서 비 스 는 C/S 모델 로 요청-응답 식 프로 토 콜 을 제공 하 는 TCP 서 비 스 를 제공 하기 때문에 클 라 이언 트 가 요청 하면 서버 에서 처리 하고 결 과 를 클 라 이언 트 로 되 돌려 줍 니 다.보통 차단 형식 으로 서버 의 응답 을 기다 리 지만 대량으로 연결 을 처리 할 때 지연 문제 가 심각 하기 때문에 Redis 는 이 문 제 를 향상 시 키 거나 보완 하기 위해파이프 기술 을 도입 했다.서버 가 제때에 응답 하지 않 을 때 클 라 이언 트 도 명령 요 구 를 계속 보 내 고 클 라 이언 트 와 서버 가 서로 간섭 하지 않 고 영향 을 주 며 서버 가 최종 적 으로 모든 서버 의 응답 을 되 돌려 줄 수 있다.이것 은 기 존의 C/S 모델 의 상호작용 을 추진 하 는 응답 속 도 를 질 적 으로 향상 시 켰 다.
다음은 Redis 파이프 메커니즘 에 대한 학습 기록 입 니 다.
Pipeline 소개
Redis 클 라 이언 트 가 명령 을 실행 합 니 다:
  • 명령 발송
  • 줄 서기 명령
  • 명령 집행
  • 복귀 결과
  • 이 중 발송 명령 과 반환 결 과 를 라운드 트 립 타임(RTT·왕복 시간)이 라 고 할 수 있다.Redis 에서 mget,mset 등 대량 조작 명령 을 제공 하여 RTT 를 효과적으로 절약 했다.그러나 대부분의 명령 은 대량 작업 을 지원 하지 않 는 다.
    이 를 위해 Redis 는 파이프(Pipeline)라 는 메커니즘 을 제공 하여 Redis 명령 을 조립 하고 RTT 를 통 해 Redis 에 전송 한 다음 에 이 Redis 명령 의 실행 결 과 를 클 라 이언 트 에 순서대로 전달 합 니 다.즉,pipeline 을 사용 하여 n 번 의 명령 을 실 행 했 고 전체 과정 은 한 번 의 RTT 만 필요 합 니 다.
    Pipeline 성능 테스트
    저 희 는 redis-benchmark 를 사용 하여 Pipeline 에 대해 성능 테스트 를 실시 합 니 다.이 도 구 는-P 옵션 을 제공 합 니 다.이 옵션 은 파이프 시스템 으로 n 개의 Redis 요청 을 처리 하고 기본 값 은 1 입 니 다.테스트 는 다음 과 같 습 니 다:
    
    #        get set 100000   
    [root@iz2zeaf3cg1099kiidi06mz ~]# redis-benchmark -t get,set -q -n 100000
    SET: 55710.31 requests per second
    GET: 54914.88 requests per second
    #   pipeline          100
    [root@iz2zeaf3cg1099kiidi06mz ~]# redis-benchmark -P 100 -t get,set -q -n 100000
    SET: 1020408.19 requests per second
    GET: 1176470.62 requests per second
    #   pipeline          10000
    [root@iz2zeaf3cg1099kiidi06mz ~]# redis-benchmark -P 10000 -t get,set -q -n 100000
    SET: 321543.41 requests per second
    GET: 241545.89 requests per second
    위의 테스트 를 통 해 알 수 있 듯 이 pipeline 을 사용 하 는 경우 Redis 는 1 초 에 처리 하 는 요청 수가 pipeline 을 사용 하지 않 는 경우 보다 훨씬 많다.
    물론 매번 pipeline 조직의 명령 개 수 를 절제 하지 않 으 면 안 됩 니 다.그렇지 않 으 면 한 번 에 Pipeline 데 이 터 를 조립 하 는 양 이 너무 많 고 한편 으로 는 클 라 이언 트 대기 시간 을 증가 하 며 다른 한편 으로 는 일정한 네트워크 차단 을 초래 할 수 있 습 니 다.
    위의 테스트 에서 도 알 수 있 듯 이 한 번 의 pipeline 조직의 명령 개 수 는 10000 이지 만 이에 대응 하 는 QPS 는 한 번 의 pipeline 명령 개 수 는 100 보다 작다.그래서 매번 Pipeline 을 조직 하 는 명령 개 수 는 많 을 수록 좋 지 않 습 니 다.한 번 에 대량의 명령 을 포함 하 는 Pipeline 을 여러 개의 작은 Pipeline 으로 나 누 어 완성 할 수 있 습 니 다.
    Pipeline 의 RTT 에 대한 설명
    홈 페이지 에 이런 설명 이 있 습 니 다.

    대체로
    Pipeline 파이프 메커니즘 은 RTT 를 줄 이기 위 한 방식 뿐만 아니 라 실제 적 으로 Redis 의 QPS 를 크게 향상 시 켰 다.파이프 메커니즘 을 사용 하지 않 은 상태 에서 데이터 구조 에 접근 하고 답장 이 발생 하 는 측면 에서 명령 마다 서 비 스 를 제공 하 는 것 이 매우 저렴 하기 때문이다.그러나 바 텀 소켓 의 측면 에서 볼 때 이것 은 매우 비 싼 것 이다.이것 은 read()와 write()시스템 호출 과 관련 되 고 사용자 상태 에서 커 널 상태 로 전환 하 는데 이런 문맥 전환 비용 은 매우 크다.Pipeline 을 사용 하 는 경우,일반적으로 하나의 read()시스템 호출 을 사용 하여 많은 명령 을 읽 은 다음,하나의 write()시스템 호출 을 사용 하여 여러 개의 답장 을 전달 하여 QPS 를 높 인 다.
    대량 명령 과 Pipeline 비교
  • 대량 명령 은 원자의 것 이 고 Pipeline 은 비원 자의 것 이다
  • 대량 명령 은 하나의 명령 으로 여러 key,Pipeline 은 여러 명령 을 지원 합 니 다
  • 대량 명령 은 Redis 서버 에서 이 루어 졌 고 Pipeline 은 서버 와 클 라 이언 트 가 공동으로 이 루어 져 야 한다
  • .
    jedis 를 사용 하여 pipeline 을 실행 합 니 다.
    
    public class JedisUtils {
     private static final JedisUtils jedisutils = new JedisUtils();
    
     public static JedisUtils getInstance() {
     return jedisutils;
     }
    
     public JedisPool getPool(String ip, Integer port) {
     JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
     jedisPoolConfig.setMaxIdle(RedisConfig.MAX_IDLE);
     jedisPoolConfig.setMaxTotal(RedisConfig.MAX_ACTIVE);
     jedisPoolConfig.setMaxWaitMillis(RedisConfig.MAX_WAIT);
     jedisPoolConfig.setTestOnBorrow(true);
     jedisPoolConfig.setTestOnReturn(true);
     JedisPool pool = new JedisPool(jedisPoolConfig, ip, port,RedisConfig.TIMEOUT,RedisConfig.PASSWORD);
     return pool;
     }
    
     public Jedis getJedis(String ip, Integer port) {
     Jedis jedis = null;
     int count = 0;
     while (jedis == null && count < RedisConfig.RETRY_NUM) {
      try {
      jedis = getInstance().getPool(ip, port).getResource();
      } catch (Exception e) {
      System.out.println("get redis failed");
      }
      count++;
     }
     return jedis;
     }
    
     public void closeJedis(Jedis jedis) {
     if (jedis != null) {
      jedis.close();
     }
     }
    
     public static void main(String[] args) throws InterruptedException {
     Jedis jedis = JedisUtils.getInstance().getJedis("127.0.0.1", 6379);
     Pipeline pipeline = jedis.pipelined();
     pipeline.set("hello", "world");
     pipeline.incr("counter");
     System.out.println("      ");
     Thread.sleep(100000);
     System.out.println("       ");
     pipeline.sync();
     }
    }
    100 s 잠 을 잘 때 Redis 를 보면 pipeline 에서 명령 이 실행 되 지 않 고 명령 이 한 대기 열 에 놓 여 있 는 것 을 볼 수 있 습 니 다.
    
    127.0.0.1:6379> get hello
    (nil)
    127.0.0.1:6379> get counter
    (nil)
    수면 이 끝 난 후pipeline.sync()를 사용 하여 이번 pipeline 대상 의 호출 을 완성 합 니 다.
    
    127.0.0.1:6379> get hello
    "world"
    127.0.0.1:6379> get counter
    "1"
    반드시 실행pipeline.sync() 해야만 최종 적 으로 명령 을 집행 할 수 있 으 며,당연히pipeline.syncANdReturnAll리 셋 메커니즘 을 사용 하여 pipeline 응답 명령 을 되 돌 릴 수 있다.
    참고 자료&감사
  • Redis 개발 과 운영
  • Using pipelining to speedup Redis queries
  • 총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기