간단한 캐싱에서 수 테라바이트 크기의 설정에 이르기까지 다양한 사용 사례에서 Redis를 사용하는 많은 사람 및 회사와 이야기할 수 있는 특권이 주어지기 때문에 다른 어떤 주제보다 더 많이 다루어야 하는 주제는 성능입니다. Redis는 성능에 접근하는 방식이 다릅니다. 대부분은 아니지만 많은 데이터베이스 서버에서 성능을 개선하려고 합니다. Redis의 목표는 속도를 늦추지 않는 것입니다. 이는 매우 다른 접근 방식이며 이를 활용하려면 다른 사고 방식이 필요합니다.
성능 지표 – 지연 시간이 왕입니까?
Redis를 사용할 때 기본적으로 두 가지 성능 메트릭이 있습니다. 초당 몇 개의 명령(또는 트랜잭션)을 실행할 수 있는지와 얼마나 오래 걸리는지입니다. 당신이 그것을 분해할 때 당신은 전자가 후자의 부차적인 결과라는 것을 알게 됩니다. Redis는 단일 스레드이기 때문에 푸시할 수 있는 작업/초 수는 작업 시간과 절대적으로 관련이 있습니다. 따라서 궁극적으로 중요한 것은 내가 "명령 대기 시간"이라고 부르는 것입니다.
Redis의 장점 중 하나는 단순성이라고 생각합니다. 쿼리가 아니라 명령을 실행합니다. 명령은 데이터를 가져오는 훨씬 간단한 경로이며 이 경우 단순성은 명령의 속도에 반영됩니다. 또한 개발자는 다양한 쿼리에 대해 최적화하려고 하는 것과 달리 최적화된 명령을 제공할 수 있습니다. 이 우아한 단순성은 Redis를 사용하는 프로그래머에게 제공됩니다. 이는 종종 서버 소프트웨어가 수행하는 대신 클라이언트 측에서 집합 필터링과 같은 "쿼리" 유형 작업을 수행하는 것을 의미합니다.
어떤 사람들은 이러한 유형의 쿼리가 서버에서 일관된 방식으로 가장 잘 수행된다고 생각하지만 현재로서는 이것이 더 이상 선호되는 경로가 아니라고 생각합니다. 그 이유는 버그베어를 "확장성"이라고 부르기 때문입니다. 예를 들어, "수평적으로 확장 가능한" 웹 서비스나 사이트를 실행하기 시작하면 이 패턴이 잘 작동한다는 것을 일찍 발견하게 될 것입니다. 그러나 "음란한" 수준의 트래픽을 처리하기 시작하면 데이터베이스에 심각한 병목 현상이 있다는 것을 빠르게 알게 됩니다. 그 후 얼마 지나지 않아 이 데이터베이스, 일반적으로 MySQL과 같은 SQL 저장소가 "수평적으로 확장 가능"하지 않다는 것을 알게 됩니다. 단순히 더 추가할 수 없습니다.
명령 지연 시간
물론 Redis도 아닙니다. 그러나 여기서 차이점은 필터링 논리, 정렬 및 단일 Redis 명령 또는 최대 몇 개의 명령으로 실행할 수 없는 모든 것을 유지함으로써 논리와 함께 DB를 로드하지 않으므로 "처리할 항목"이 없다는 것입니다. . Redis는 기존의 "데이터베이스 서버"가 아닌 "데이터 저장소"로 사용해야 합니다. 이것이 "Redis의 속도를 늦추지 마십시오"의 첫 번째 측면입니다. Lua 스크립팅 경로를 시작하면 순 성능 저하의 위험이 있음을 언급할 필요가 없습니다. 트래픽이 낮거나 보통일 때는 개발 중인 것을 볼 수 없습니다. 그러나 큰 스케일을 치면 볼 수 있습니다. 그리고 그때쯤이면 논리가 너무 자주 이미 구워져 애플리케이션 코드로 옮기기에는 엄청난 기술적 부채가 됩니다. 기술 부채를 청산하는 데 얼마나 많은 우선 순위가 부여되는지 우리는 모두 알고 있습니다.
이것은 Lua 스크립팅에 자리가 없다는 말은 아닙니다. 그것은 단지 그것을 철저히 조사해야 함을 의미합니다. Lua 스크립트가 순 성능 손실인지 아닌지에 대한 좋은 규칙은 해당 논리 클라이언트 측을 처리하는 경우 실행해야 하는 추가 왕복 비용을 비교하는 것입니다. 그러나 클라이언트 코드가 이를 수행할 수 있는 기간이 아닙니다. 이렇게 생각해 보세요. 왕복 비용을 2ms 줄이면서 스크립트 실행 시간에 3ms를 추가하면 잘못된 방향으로 가게 됩니다.
여기서 우리는 단일 스레드 서버의 특성을 잘 알고 있어야 합니다. 3ms 스크립트는 실행되는 동안 잠재적으로 수백(또는 수천)의 명령을 차단합니다. (pull) -> (logic) -> (pull) 시퀀스로 분할하면 서버는 "(논리)" 단계에서 추가 요청을 처리할 수 있습니다. 클라이언트 코드에 논리를 유지함으로써 다중 클라이언트 기반 시스템 고유의 동시성을 보존합니다. 트랜잭션이나 Lua 스크립팅이 필요한 경우 당연히 사용하십시오. 그러나 코드를 "더 쉽게" 만드는 것처럼 보이기 때문에 사용하지 마십시오. 동시성 성능 히트를 항상 인식하고 측정하고 의식적으로 선택하십시오.
이것은 "Redis Down을 늦추지 마십시오"라는 두 번째 규칙으로 이어집니다. 스크립트를 통해 서버 로직을 피함으로써 동시성을 유지합니다. 여러 키에서 작동하는 Lua 스크립트를 재작성하거나 덤프하지 않고도 Redis 클러스터 설정으로 마이그레이션할 수 있는 이점이 있습니다.
Redis를 느리게 할 수 있는 다른 방법
Redis를 느리게 할 수 있는 Redis 서버 실행의 몇 가지 시스템 수준 또는 운영 측면이 있습니다. I/O 리소스 제한을 사용하는 모든 서버와 마찬가지로 Redis가 느려질 수 있습니다. 예를 들어 8GB의 네트워크 대역폭이 필요하지만 1GB가 있는 경우 "느립니다". 데몬 프로세스가 필요한 것보다 적은 수의 열린 소켓으로 제한되어 있으면 명령을 실행하는 대신 연결이 닫힐 때까지 대기하는 데 동시 연결 시간이 소요됩니다.
Redis의 속도를 저하시키는 가장 일반적인 두 가지 운영 선택은 1) 가상 머신, 특히 Xen 하이퍼바이저 기반의 가상 머신에 배치하는 것과 2) 대용량 디스크 지속성입니다.
첫 번째 것은 표준 Redis 문헌에서 상당히 잘 설명되어 있습니다. Xen 하이퍼바이저 VM에 넣지 마십시오. 두 번째는 지속성인 것 같지만 내 예상으로는 충분하지 않습니다.
물론 표준 권장 사항이 있습니다. 로컬 고속 디스크를 사용하고 지속 시 CoW 댄스를 처리하기에 충분한 메모리가 있는지 확인하십시오. 심지어 슬레이브에서만 지속성을 실행하는 경우에도 마찬가지입니다. 이는 실제로 명령 대기 시간에 영향을 미칠 수 있습니다. 누락된 것은 해당 여부를 적절하게 판별하는 방법입니다.
이를 테스트하는 한 가지 표준 방법은 내장된 대기 시간 테스트를 사용하는 것입니다. 이를 수행하는 방법에 대한 기술적인 세부 사항에 들어가기 전에 더 큰 "방법"에 대한 질문에 답하고 싶습니다. 여기서 주요 하위 집합은 이러한 테스트를 실행할 때입니다. 첫째, 이 테스트는 데이터 세트가 작은 경우 무의미할 수 있습니다. 얼마나 작습니까? 데이터를 디스크에 덤프하는 데 걸리는 시간을 결정합니다. 우리가 1~2초, 어쩌면 10초를 이야기한다면 의미 있는 데이터를 얻을 가능성이 적습니다. 물론 이것은 모두 SAVE가 아닌 BGSAVE를 수행한다는 전제하에 있습니다.
지속성 대기 시간
이것은 내가 "지속성 대기 시간"이라고 부르는 것의 첫 번째 원칙으로 이어집니다. 명령이 서버에 도달한 후 결과가 어떤 형태의 지속성에 도달할 때까지의 시간입니다. 가능한 지속성 옵션을 도입하는 최소 대기 시간을 찾으십시오. 네트워크 및 디스크에 따라 AoF 또는 Slave 서버가 가장 낮은 대기 시간 범핑 지속성 옵션이 되며 RDB가 마지막에 옵니다.
RDB는 T 초 동안 N 변경의 내장 지연이 있기 때문에 주로 마지막에 올 것입니다. 따라서 최소 기간(최소 기본 창은 60초)에 충분한 변경 사항이 있다고 가정하면 지속성 지연은 간격 T + RDB를 디스크에 쓰는 시간입니다. 기본 60초 간격으로 해당 메모리를 디스크에 덤프하는 데 30초가 걸린다면 "지속성 대기 시간"은 (60+30) 90초가 됩니다.
그러나 이것은 이 지속성 대기 시간이 문제인지 여부에 대한 질문을 던집니다. 이 질문에는 두 가지 측면이 있습니다. 1) 비즈니스 요구 사항에 충분합니까? 2) Redis 속도가 느려지나요?
첫 번째 질문은 모든 사람에게 대답하는 일반적인 답변을 제공할 수 없다는 것입니다. 그러나 지속성 대기 시간에 대한 요구 사항이 위의 공식보다 더 엄격하다면 RDB 대신 "슬레이브 및/또는 AoF를 사용"하는 경향이 있는 답변을 얻을 수 있을 것입니다. 이것은 Redis를 실행하는 플랫폼에서 명백한 실수를 하지 않는다고 가정합니다. 두 번째 측면은 무엇입니까? Redis가 느려지는가?
어떤 사람들에게는 "RDB 파일을 저장하는 데 얼마나 걸립니까?"라는 질문이 가장 중요하게 생각됩니다. 제 생각에는 이것은 실수입니다. 시간이 얼마나 걸리든 상관없나요? 이 질문에 대한 대답은 "저장하면 Redis 속도가 느려지나요?"입니다. 그렇지 않다면 1초가 걸리든 1시간이 걸리든 신경쓰지 않아도 됩니다. 예를 들어, RDB를 저장하는 데 1000초가 걸리는 서버 A를 고려하십시오. 고유 명령 대기 시간 범위를 저장하지 않는 동안 30-100마이크로초입니다. 저장하는 동안 이 대기 시간은 여전히 30-100마이크로초 범위입니다. 이 경우 Redis 성능이 좋지 않다는 생각 하에 이 RDB 절약 시간을 줄이는 작업을 하는 것은 시기상조입니다.
그러나 서버 B는 10초 밖에 걸리지 않지만 명령 대기 시간은 30-100us에서 130-250us로 점프합니다. 이제 저장으로 인해 Redis 속도가 느려지고 이를 최소화하려고 하기 때문에 RDB 파일을 생성하는 데 걸리는 시간에 대해 걱정해야 할 이유가 있습니다. 그것이 더 빠른 디스크를 의미한다면 적어도 지금은 정당화할 이유가 있습니다. 약 100-150마이크로초의 증가가 애플리케이션에 대한 성능 불안을 야기한다고 가정합니다. 그렇지 않으면 조기 최적화로 돌아갑니다.
이제 이 지연 시간을 측정하는 방법에 관해서는 이 게시물이 이미 상당히 길어졌기 때문에 이 게시물의 2부에서 더 자세히 설명하겠습니다.