일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- GC
- Kotlin
- Stack
- 이스티오
- 스프링
- list
- mysql
- 자바 ORM 표준 JPA 프로그래밍
- redis
- JPA
- Real MySQL
- thread
- 자바
- K8s
- jvm
- gradle
- 보조스트림
- SpringBoot
- spring
- 토비의 스프링 정리
- IntellJ
- MSA
- 백준
- OS
- Java
- 토비의 스프링
- 스트림
- Stream
- Collection
- 쿠버네티스
- Today
- Total
인생을 코딩하다.
[Redis] Redis Pipeline 본문
Redis Pipeline에 설명하기에 앞서 No Pipeline에 관해 간략하 말씀드리겠습니다.
redis는 요청을 보낼 때 일반적으로 아래와 같이 수행됩니다.
- 클라이언트는 서버에 쿼리를 보내고 일반적으로 차단 방식으로 소켓에서 서버 응답을 읽습니다.
- 서버는 명령을 처리하고 클라이언트에 응답을 다시 보냅니다.
Redis는 클라이언트-서버 모델과 요청/응답 프로토콜을 사용하는 TCP 서버이며, 클라이언트가 서버에 명령을 보내고 응답을 받는 구조입니다.
위 과정은 클라이언트가 연속적으로 많은 요청을 보내야 하는 경우 RTT가 길어져 성능에 악영향을 미칠 수 있습니다. 예를 들어 RTT가 250밀리초인 경우, 초당 최대 4개의 요청만 처리할 수 있습니다. 만약 요청이 1000개라면 엄첨 느리겠죠?
위와 같이 RTT가 길어지는 상황을 개선하기 위해서는 어떤 방법이 존재할까요? 네트워크 연결을 최적화하고, 명령을 일괄 처리하는 파이프라인으로 전송하는 방법을 고려할 수 있습니다. 이러한 최적화는 Redis 성능을 향상시키는 데 도움이 됩니다.
* RTT -> 클라이언트가 명령을 보내고 서버가 응답을 반환하는 데 걸리는 시간, RTT는 네트워크 연결의 속도에 따라 다르며 인터넷을 통한 연결이 느릴수록 RTT가 길어짐
Redis Pipeline이란?
Redis Pipeline은 개별 명령에 대한 응답을 기다리지 않고 한 번에 여러 명령을 실행하여 성능을 향상시키는 기술입니다.
Pipeline 동작 과정
- Redis 클라이언트와 서버 연결: 먼저 Redis 클라이언트가 Redis 서버에 연결합니다. 클라이언트와 서버 간의 TCP/IP 연결이 설정됩니다.
- 파이프라인 시작: 클라이언트는 파이프라인을 시작합니다. 이때, 여러 개의 Redis 명령을 파이프라인에 추가할 수 있습니다.
- 여러 명령 추가: 클라이언트는 파이프라인에 여러 개의 Redis 명령을 추가합니다. 이 명령들은 일련의 작업을 수행하는데 사용됩니다. 예를 들어, SET, GET, HSET, HGET 등 다양한 명령이 추가될 수 있습니다.
- 파이프라인 실행: 파이프라인에 추가된 명령들은 클라이언트가 EXECUTE 또는 SEND 명령을 호출하기 전까지 서버로 전송되지 않습니다.
- 서버로 명령 일괄 전송: 클라이언트가 EXECUTE 또는 SEND 명령을 호출하면, 파이프라인에 추가된 모든 명령이 일괄로 Redis 서버로 전송됩니다. 이때, 네트워크 오버헤드를 최소화하기 위해 모든 명령이 한 번에 전송됩니다.
- 서버에서 명령 처리: Redis 서버는 파이프라인에 추가된 모든 명령을 받아 처리합니다. 명령들은 순서대로 처리되며, 각 명령의 결과가 서버에서 생성됩니다.
- 클라이언트 응답 수신: Redis 서버는 명령을 순서대로 실행하고, 각 명령의 결과를 클라이언트에게 응답으로 보냅니다. 클라이언트는 이 응답을 받아 처리합니다.
- 파이프라인 결과 반환: 클라이언트가 파이프라인 실행 결과를 수신하면, 각 명령의 결과를 추출하여 사용자나 응용 프로그램에 반환합니다. 결과는 명령이 실행된 순서대로 반환됩니다.
- 파이프라인 종료: 파이프라인은 실행이 완료된 후 종료됩니다. 클라이언트는 필요한 경우 다시 파이프라인을 시작할 수 있습니다.
이러한 과정을 통해 Redis 파이프라인은 여러 명령을 일괄로 처리하여 네트워크 오버헤드를 줄이고 성능을 향상시킬 수 있습니다.
그림은 notion mermaid로 그렸고 mermaid code는 아래 더보기 참고 부탁드립니다.
graph TD;
subgraph "파이프라인 사용"
A[연결 설정]
B[파이프라인 시작]
C[여러 명령 추가]
D[파이프라인 실행]
E[클라이언트 응답 수신]
F[파이프라인 결과 반환]
G[파이프라인 종료]
end
subgraph "파이프라인 미사용"
H[연결 설정]
I[명령1 실행]
J[명령2 실행]
K[명령3 실행]
L[명령4 실행]
M[명령5 실행]
N[클라이언트 응답 수신]
end
A -->|연결 요청| B
B -->|파이프라인 시작| C
C -->|여러 명령 추가| C
C -->|명령1 실행| C
C -->|명령2 실행| C
C -->|명령3 실행| C
C -->|명령4 실행| C
C -->|명령5 실행| D
D -->|파이프라인 실행| E
E -->|클라이언트 응답| F
F -->|파이프라인 결과 반환| G
G -->|파이프라인 종료| N
H -->|연결 요청| I
I -->|명령1 실행| J
J -->|명령2 실행| K
K -->|명령3 실행| L
L -->|명령4 실행| M
M -->|명령5 실행| N
N -->|클라이언트 응답| N
어떤 상황에서 사용하나요?
- 성능 향상: Redis 파이프라인을 사용하면 여러 Redis 명령을 한 번에 보내서 네트워크 오버헤드를 줄일 수 있습니다. 이는 대량의 작업을 수행해야 할 때 특히 유용합니다.
- 원자성 보장: 파이프라인을 사용하면 여러 명령을 하나의 트랜잭션으로 처리할 수 있으므로 Redis 서버는 이러한 명령을 원자적으로 실행합니다. 이로써 여러 개의 명령이 중간에 실패하더라도 이전 상태로 롤백되지 않고 일괄 처리됩니다.
- 비동기 작업: Redis 파이프라인은 명령을 일괄로 보내기 때문에 클라이언트에서 서버로 대량의 작업을 비동기적으로 보낼 때 유용합니다. 이를 통해 작업을 병렬로 처리하고 응답을 기다리는 시간을 줄일 수 있습니다.
- 대량 데이터 처리: Redis 파이프라인은 대량의 데이터를 처리할 때 유용합니다. 예를 들어, 여러 개의 값을 한 번에 쓰거나 읽어야 하는 경우에 사용할 수 있습니다.
- 실행 속도 향상: 일련의 연관된 작업을 한 번에 실행하려면 파이프라인을 사용하여 작업의 전체 성능을 향상시킬 수 있습니다.
- 실시간 분석 및 통계: Redis는 실시간 데이터 분석 및 통계에 매우 적합한 데이터베이스입니다. 파이프라인을 사용하여 여러 명령을 조합하여 실시간으로 데이터를 분석하고 집계할 수 있습니다.
그러나 파이프라인을 사용할 때 주의할 점이 있습니다. 파이프라인에서 여러 개의 명령을 보낸 경우, 그 명령들은 동시에 실행되기 때문에 순서가 중요하다는 점을 고려해야 합니다.
아래는 간단한 예제 코드 입니다. 얼마나 성능 최적화가 가능한지 직접 실험해보세요ㅎㅎ
.. 생략
val result = redisTemplate.executePipelined(RedisCallback<Any> { connection ->
val keySerializer: RedisSerializer<String> = StringRedisSerializer()
val valueSerializer: RedisSerializer<String> = StringRedisSerializer()
connection.openPipeline()
val keyToValue = mapOf(
"a" to "1",
"b" to "2",
"c" to "3"
)
keyValues.forEach { (key, value) ->
connection.set(keySerializer.serialize(key), valueSerializer.serialize(value))
}
connection.closePipeline()
null
})
.. 생략
'DataBase' 카테고리의 다른 글
[DB] reWriteBatchedInserts, rewriteBatchedStatements (2) | 2024.02.07 |
---|---|
postgreSql using brin index란? (0) | 2023.12.20 |
[mySql, postgreSql] where절과 join절 작성 순서는 query의 성능과 연관이 있을까요? (0) | 2023.05.06 |
[MySQL] MySQL 실행 계획 분석을 통해 페이징 쿼리 성능 개선 (0) | 2021.08.28 |
[MySQL] 외래키(Foreign Key)와 데드락(DeadLock) (0) | 2021.08.12 |