HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
✍🏻
Learnary (learn - diary)
/
Redis 네트워크 병목현상 개선

Redis 네트워크 병목현상 개선

progress
Done
Tags
Database
Redis 네트워크 병목현상?문제 상황파이프라이닝 효과 요약Refer

Redis 네트워크 병목현상?

왼쪽 형광색 막대를 우리가 개발하는 개발 서버이고 오른쪽 파란색 막대는 서버 오른쪽은 레디스 서버이다.
notion image
 
왼편의 그림 같은 경우 레디스와 연달아 통신하고 있고 오른쪽은 연달아 하기 보다는 하나의 통신으로 필요한 데이터들을 한번에 처리하고 있는 그림이다.
해당 그림 표현에서 TCP 요청 과정이 숨어 있다는 것을 알고 있어야한다.
 
보통 레디스는 싱글스레드와 이벤트루프 기반으로 비동기 방식으로 요청을 처리하기 때문에 보조데이터베이스로 주로 사용되어지며 성능적 향상을 기대할 수 있는 기술로 잘알려져있지만 기본적인 CS 개념을 잘 알고 있어야 한다.
 
 

문제 상황

나의 프로젝트에서 특히 redis에 각 상품별 평점에 대한 정보를 저장했고 평점을 매기기 위해 1점부터 5점까지 redisTemplate로 하나씩 가져오고 있었다.
notion image
해당 부분에서 우려한 것은 데이터의 범위가 넓어지면 넓어질 수록 TCP 3way, 4way 연결을 맺는 부분이였다.
일정 시간동안 한번에 연결하도록 하는 무언가가 있지 않을까란 생각이 있었지만, 없는 줄 알았다.여러 프로젝트를 순회하면서 “레디스 파이프라인 성능 개선하기” 라는 문구를 찾게 되었다.
 
RedisTemplate을 통해 여러 데이터들을 삽입하거나 가져오는 상황에서 레디스는 기본적으로 O(1) 시간 복잡도가 소요되지만 TCP 연결 방식을 이용하면서 네트워크I/O에 대해서 병목 생길 수 있는 가능성이 있다고 한다.
왜냐하면 매요청마다 응답을 받기 때문에 Blocking이 발생하게 되기 때문이다.
즉, 수십만개의 요청을 받는다면 부하가 생기고 RTT로 인해 오버헤드가 발생하게 된다.
RTT란?
네트워크에서 데이터 패킷이 송신 지점에서 수신 지점까지 전송되고 돌아오는 데 걸리는 시간을 나타낸다.
즉 한 번의 왕복 시간이다.
 
하지만 레디스에서는 RDBMS 처럼 벌크 연산을 지원하지 않지만 HTTP 기반으로 통신하기 때문에 파이프라이닝을 지원한다.
notion image
 
파이프라이닝은 클라이언트와 서버 간의 통신을 효율적으로 처리하여 레디스의 처리량을 높이는 방법으로 여러 개의 요청을 한 번에 보내고 응답을 기다리지 않고 다음 요청을 보내는 방식이다.
레디스에서 지원해주는 pipeline api인 executePipelined 메소드를 이용해 레디스에 연결을 한후 모든 원소들에 대한 처리를 이어간뒤 연결을 닫는다.
 
 
notion image
 
이전보다 처리량이 300ms → 58ms 감소한 결과를 보여줬다.
코드적으로 신경쓰이는 부분은 null이 있다는 것이다.
 
파이프라이닝에서 주의할 사항이 있다.
  1. 파이프라이닝은 네트워크 오버헤드를 줄이고 응답 시간을 최적화하는 데 도움이 되지만모든 요청에 대한 응답을 기다리지 않고 연속적으로 요청을 보내기 때문에, 요청 순서가 중요한 경우에는 주의해야 한다. 또한 파이프라이닝을 사용하기 위해서는 클라이언트와 서버가 파이프라이닝 프로토콜을 지원해야 하는 사실을 염두해 두어야 한다.
  1. 이미 클러스터 모드라면 샤딩되어 분산되어 저장한다는 사실을 알고 있을 것이다.
    1. 이점을 간과한체 무턱대고 한다면 서로 다른 노드들에서 꺼내기 때문에 비효율적일 수 있다. 만약 태그 기반으로 하나의 노드에 저장했다면 사용하는 것이 더 좋을 것이다.
 
 

파이프라이닝 효과 요약

 
장점: 네트워크 비용 절감으로 인해 처리량 향상
단점: 순서에 의존하는 로직인 경우 사용할 수 없으며, 클라이언트 서버가 파이프라이닝 프로토콜을 지원하는지 확인해야 한다.
 
 

Refer

spring-data-redis/pipelining.adoc at main · spring-projects/spring-data-redis
Provides support to increase developer productivity in Java when using Redis, a key-value store. Uses familiar Spring concepts such as a template classes for core API usage and lightweight reposito...
spring-data-redis/pipelining.adoc at main · spring-projects/spring-data-redis
https://github.com/spring-projects/spring-data-redis/blob/main/src/main/asciidoc/reference/pipelining.adoc
spring-data-redis/pipelining.adoc at main · spring-projects/spring-data-redis
HTTP/1.x의 커넥션 관리 - HTTP | MDN
커넥션 관리는 HTTP의 주요 주제입니다: 대규모로 커넥션을 열고 유지하는 것은 웹 사이트 혹은 웹 애플리케이션의 성능에 많은 영향을 줍니다. HTTP/1.x에는 몇 가지 모델이 존재합니다: 단기 커넥션, 영속적인 커넥션, 그리고 HTTP 파이프라이닝.
HTTP/1.x의 커넥션 관리 - HTTP | MDN
https://developer.mozilla.org/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x
HTTP/1.x의 커넥션 관리 - HTTP | MDN
[#2] Redis에 한번에 많은 데이터 추가 시 네트워크 병목 개선하기 - Redis Pipeline 이용하기
문제 상황 예를들어 레디스에 리스트를 저장하였고 그 리스트에 한번에 여러개의 원소를 추가하는 상황이라고 가정해보겠습니다. 레디스에 기본적으로 한번의 추가 연산을 하면 O(1)시간이 들며 요청을 보내고 다음과 같이 응답 값을 받습니다. 레디스는 싱글스레드와 이벤트루프 기반으로 비동기방식으로 요청을 처리하기 때문에 고성능입니다. 하지만 기본적으로 TCP 기반의 네트워크 모델을 따르기 때문에 네트워크 I/O 에서 병목이 생길 수 있는 가능성이 있습니다. 하지만 매번 요청을 할 때마다 응답값을 받기 때문에(요청을 보내고 응답을 받을때까지는 blocking이 됩니다) 한번에 수십만개의 요청을 보낸다면 이 응답값을 매번 받는 것도 부하가 생길 수 있습니다. 즉, 레디스 서버에 반복문을 돌며 여러번 리스트의 원소를 ..
[#2] Redis에 한번에 많은 데이터 추가 시 네트워크 병목 개선하기 - Redis Pipeline 이용하기
https://tjdrnr05571.tistory.com/7
[#2] Redis에 한번에 많은 데이터 추가 시 네트워크 병목 개선하기 - Redis Pipeline 이용하기