[트러블 슈팅] Redis too many connection - 100-hours-a-week/5-yeosa-wiki GitHub Wiki
1. 개요
-
멀티 프로세스 + 레디스 테스트를 vm 환경에서 했을때, redis too many connection 에러가 발생했음.
-
이에 원인을 분석하여 문제를 해결하고자 함.
2. 원인 분석
a. 가설: FastAPI 서버에서 레디스 커넥션 풀을 이용하지 않고 있을 것이다. - 거짓
가. Redis connection pool 생성
def init_redis() -> Redis:
global _redis
pool = ConnectionPool(
host=REDIS_HOST,
port=REDIS_PORT,
db=REDIS_DB,
max_connections=20,
decode_responses=True,
)
_redis = Redis(connection_pool=pool)
return _redis
def get_redis() -> Redis:
if _redis is None:
raise RuntimeError("Redis가 초기화되지 않았습니다.")
return _redis
나. 워커 프로세스 실행 시, Redis connection pool 초기화
app.state.redis = init_redis()
다. 캐시를 이용해야 하는 부분에서 이용
async def get_cached_embedding(key: str) -> Any | None:
redis = get_redis()
b. 문제 식별: max_connections 크기가 작음
async def get_cached_embeddings_parallel(keys: list[str]) -> tuple[list[Any | None], list[str]]:
"""
비동기로 여러 키를 Redis에서 조회합니다. 실패한 키도 기록합니다.
"""
t0 = time.perf_counter()
results = await asyncio.gather(
*(get_cached_embedding(key) for key in keys),
return_exceptions=True
)
- 워커에서 캐시 조회가 필요한 경우
- get_cached_embeddings_parallel 메서드에서 get_cached_embedding를 사진 장수(임베딩 수)만큼 호출
- 30장짜리 요청에서 커넥션 30개를 필요로 함
- Redis connection pool에서 max_connection 20으로 설정함
- 이로 인해 Too many connection 에러 발생
3. 해결
a. 해결 방안: 워커 프로세스 당 커넥션풀 크기 100으로 증가
- Redis 설정 확인 결과, 위와 같이 10000개의 연결 허용
- 워커 프로세스 당 100의 연결을 허용함
- 그 결과, 에러 발생하지 않음
b. 추후 고려: 워커 프로세스 당 커넥션 풀 크기 고민
- gunicorn에서 권장하는 워커 프로세스 개수는 vCPU 개수*2 + 1
- 만약 4vCPU 서버에서 8개 워커 프로세스 생성하면 800개의 연결 생성
- 많은 연결을 생성하는 것이 Redis 서버에 오버헤드가 되지 않는지 고려 필요.