많은 수의 연결(Valkey 및 Redis OSS) - Amazon ElastiCache

많은 수의 연결(Valkey 및 Redis OSS)

서버리스 캐시와 각 ElastiCache(Redis OSS) 노드는 최대 65,000개의 동시 클라이언트 연결을 지원합니다. 하지만 성능을 최적화하려면 클라이언트 애플리케이션이 해당 연결 수준에서 계속 작동하지 않는 것이 좋습니다. Valkey와 Redis OSS는 각각 들어오는 클라이언트 요청이 순차적으로 처리되는 이벤트 루프를 기반으로 하는 단일 스레드 프로세스입니다. 즉, 연결된 클라이언트 수가 늘어날수록 해당 클라이언트의 응답 시간이 길어집니다.

Valkey 또는 Redis OSS 서버에서 연결 병목 현상이 발생하지 않도록 다음과 같이 조치를 취할 수 있습니다.

  • 읽기 전용 복제본에서 읽기 작업을 수행합니다. 이렇게 하려면 클러스터 모드가 비활성화된 상태에서 ElastiCache 리더 엔드포인트를 사용하거나, 클러스터 모드가 활성화된 상태에서 읽기 전용 복제본(서버리스 캐시 포함)을 사용하여 수행할 수 있습니다.

  • 쓰기 트래픽을 여러 프라이머리 노드에 분산합니다. 2가지 방법으로 수행할 수 있습니다. Valkey 또는 Redis OSS 클러스터 모드 지원 클라이언트와 함께 다중으로 샤딩된 클러스터를 사용할 수 있습니다. 클라이언트 측 샤딩이 비활성화된 클러스터 모드에서 여러 프라이머리 노드에 쓸 수도 있습니다. 이 작업은 서버리스 캐시에서 자동으로 수행됩니다.

  • 클라이언트 라이브러리에서 사용 가능한 경우 연결 풀을 사용하세요.

일반적으로 TCP 연결을 생성하는 작업은 일반적인 Valkey 또는 Redis OSS 명령보다 계산 비용이 많이 듭니다. 예를 들어 기존 연결을 재사용할 경우 SET/GET 요청을 처리하는 속도가 훨씬 빠릅니다. 크기가 한정된 클라이언트 연결 풀을 사용하면 연결 관리 시의 오버헤드가 줄어듭니다. 또한 클라이언트 애플리케이션에서 동시에 들어오는 연결 수를 제한합니다.

PHPRedis의 다음 코드 예제는 새 사용자 요청별로 새 연결이 생성된다는 것을 보여 줍니다.

$redis = new Redis(); if ($redis->connect($HOST, $PORT) != TRUE) { //ERROR: connection failed return; } $redis->set($key, $value); unset($redis); $redis = NULL;

이 코드를 Graviton2(m6g.2xlarge) ElastiCache(Redis OSS) 노드에 연결된 Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스에서 루프로 벤치마킹했습니다. 클라이언트와 서버를 동일 가용 영역에 배치했습니다. 전체 작업의 평균 지연 시간은 2.82밀리초였습니다.

코드를 업데이트하고 영구 연결과 연결 풀을 사용했을 때 전체 작업의 평균 지연 시간은 0.21밀리초였습니다.

$redis = new Redis(); if ($redis->pconnect($HOST, $PORT) != TRUE) { // ERROR: connection failed return; } $redis->set($key, $value); unset($redis); $redis = NULL;

필수 redis.ini 구성:

  • redis.pconnect.pooling_enabled=1

  • redis.pconnect.connection_limit=10

다음 코드는 Redis-py 연결 풀의 예제입니다.

conn = Redis(connection_pool=redis.BlockingConnectionPool(host=HOST, max_connections=10)) conn.set(key, value)

다음 코드는 Lettuce 연결 풀의 예제입니다.

RedisClient client = RedisClient.create(RedisURI.create(HOST, PORT)); GenericObjectPool<StatefulRedisConnection> pool = ConnectionPoolSupport.createGenericObjectPool(() -> client.connect(), new GenericObjectPoolConfig()); pool.setMaxTotal(10); // Configure max connections to 10 try (StatefulRedisConnection connection = pool.borrowObject()) { RedisCommands syncCommands = connection.sync(); syncCommands.set(key, value); }