[입 개발] Redis Pipeline

해당 블로그는 KT Olleh UCloudBiz의 지원을 받고 있습니다.

가끔씩 Redis의 성능을 좀 더 극대화 시키고 싶어하시는 분들이 있으시기 때문에, 오늘은 이에 가장 많이 사용되는 Pipeline에 대해서 설명을 할려고 합니다.

먼저 재미난 사실을 알려드리자면, Redis pipeline이라는 것이 성능 향상을 위해서 유리하다라는 것은 많은 분들이 알고계시지만, 사실, 서버에는 Redis pipeline 라는 기능이 없다는 것입니다.

다음과 같은 명령을 Redis 소스에서 확인해보면, redis-benchmark.c 와 redis-cli.c를 빼고는 아무데도 pipe라는 글자자체가 없다는 것을 알 수 있습니다.

grep pipe src/* -Rn

그렇다면 Pipeline의 정체는 무엇일까요? 먼저 Pipeline을 적용한 테스트와 Pipeline을 적용하지 않은 테스트 결과를
보여드리도록 하겠습니다.

언어는 python 에 KT Olleh UCloudBiz 의 8vcore 16GB 메모리 모델을 사용했습니다.
두 대를 사용해서 한대는 redis-server unstable 버전이 설치되어 있고, 다른 서버에서 접속한 버전입니다.

from multiprocessing import Process
import redis
import random
import string

def id_generator(size=6, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for x in range(size))

data = id_generator(512, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()")

def f(idx):
    print 'PR', idx
    r = redis.StrictRedis(host='172.27.217.193', port=6379, db=0)
    for i in xrange(idx * 1024 * 1024, (idx+1)*1024*1024):
        key = 'PR%s'%(i)
        r.get(key)

if __name__ == '__main__':
    print data
    pids = []
    for i in xrange(80):
        p = Process(target=f, args=(i,))
        pids.append(p)
        p.start()

    for pid in pids:
        pid.join()

redis-not-pipeline위의 그림을 보면 55k 에서 65k 수준의 cmd/s 를 볼 수 있습니다.

이제 Pipeline을 적용한 테스트를 한번 보도록 하겠습니다. 다른 부분은 동일하고 함수 f()만 조금 수정되었습니다.

def f(idx):
    print 'PR', idx
    r = redis.StrictRedis(host='172.27.217.193', port=6379, db=0)
    pipeline = r.pipeline()
    for i in xrange(idx * 1024 * 1024, (idx+1)*1024*1024):
        key = 'PR%s'%(i)
        pipeline.get(key)
        if (i != idx * 0124 * 1024 and i%1024==0):
            pipeline.execute();

redis-pipeline

물론 거의 200k 전후로 cmd/s 가 나오는 것을 볼 수 있습니다. 도대체 pipeline은 무엇이길래, 이런 속도차를 보여주는 것일까요?

사실 pipeline을 이용해서 가지게 되는 이점은 다음과 같습니다.
1. 명령들이 뭉쳐서 전달되기 때문에, 클라이언트 입장에서는 함수 콜이 줄어들고, 서버 입장에서도 I/O가 적게 발생합니다.
2. 보통 하나의 명령을 보내면 결과를 확인하는 시점이 있는데, 이미 서버에서는 다음 명령이 실행되고 있기 때문에 이런 시간이 줄어듭니다.

실제로 memcached 나 redis를 쓸 때, 한 서버와 통신할 때 mget등을 이용해서 명령어 전송 수를 줄이는 것도 일종의 튜닝 방법입니다. 사실 서버입장에서는 명령어가 뭉쳐서 들어와서 시스템 콜이 줄어드는 이점 이외에는 아무런 차이가 없지만… 심할때는 위와 같은 차이가 나는 것입니다.

About these ads

2 comments on “[입 개발] Redis Pipeline

  1. 좋은 글 감사합니다. redis 는 single thread니까 하나의 pipeline에 너무 많은 명령을 묶으면 다른 클라이언트의 응답이 일방적으로 밀려버리는 일도 발생할 것 같은데. pipeline을 각각의 명령어로 순차적으로 처리하는 과정에 다른 client의 요청이 중간에 끼여서 우선 처리 될 수도 있나요? 어떻게 되나요?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s