>  기사  >  데이터 베이스  >  Redis 지식 포인트를 분석하는 방법

Redis 지식 포인트를 분석하는 방법

WBOY
WBOY앞으로
2023-06-03 20:02:11995검색

유형이 아니라 데이터 구조입니다

많은 기사에서 Redis가 일반적으로 사용되는 5가지 데이터 유형을 지원한다고 말합니다. 이는 실제로 큰 모호성입니다. Redis에 저장된 모든 바이너리 데이터는 실제로 바이트 배열(byte[])입니다. 이러한 바이트 데이터는 적절한 형식으로 디코딩한 후에만 문자열, 정수 또는 객체로 변환될 수 있습니다. 데이터 유형이 있습니다.

이 점 꼭 기억해두세요. 따라서 바이트 배열(byte[])로 변환할 수 있는 모든 항목은 redis에 저장할 수 있습니다. 문자열, 숫자, 사물, 그림, 소리, 비디오, 파일 등 무엇이든 바이트 배열로 변환되기만 하면 처리할 수 있습니다.

그래서 Redis의 문자열은 실제로 가장 간단한 데이터 구조를 나타냅니다. 즉, 하나의 키는 하나의 값에만 대응할 수 있습니다. 여기서 키와 값은 모두 바이트 배열이지만 키는 일반적으로 문자열을 변환한 바이트 배열이며 값은 실제 필요에 따라 결정됩니다.

특정 상황에서는 값에 대한 몇 가지 요구 사항도 있습니다. 예를 들어 자동 증가 또는 자체 감소 작업을 수행하려면 값에 해당하는 바이트 배열을 숫자로 디코딩할 수 있어야 합니다. 오류가 보고됩니다.

그래서 List의 데이터 구조는 실제로 하나의 키가 여러 값에 대응할 수 있고, 값이 순서대로 있고, 값 값이 반복될 수 있다는 것을 의미합니다.

Set은 하나의 키가 여러 값에 대응할 수 있고 값 사이에 순서가 없으며 값 값이 반복될 수 없음을 의미하는 데이터 구조입니다.

해시는 하나의 키가 여러 키-값 쌍에 대응할 수 있음을 의미하는 데이터 구조입니다. 이때 이러한 키-값 쌍 사이의 순서는 일반적으로 이름 의미에 따라 액세스되는 데이터 구조입니다. 및 비 위치 의미론.

Sorted Set은 하나의 키가 여러 값에 대응할 수 있음을 의미하는 데이터 구조입니다. 값은 크기별로 정렬되며 값은 반복될 수 없습니다. 각 값은 점수라는 부동 소수점 숫자와 연결됩니다. 요소 정렬 규칙은 먼저 점수별로 정렬한 다음 값별로 정렬하는 것입니다.

이제 여러분은 이 5가지 데이터 구조에 대해 더 명확하게 이해하셨고 그에 상응하는 명령이 여러분에게 작은 사례라고 믿습니다.

클러스터가 가져오는 문제와 해결책

클러스터가 가져오는 이점은 용량 증가, 처리 능력 향상, 필요에 따른 동적 확장 및 축소 등 명백합니다. 그러나 이는 또한 적어도 다음 두 가지와 같은 몇 가지 새로운 문제를 야기할 것입니다.

데이터 할당에는 저장 중에 데이터가 저장되는 노드를 결정하고 검색 중에 데이터를 쿼리하는 노드를 결정하는 것이 포함됩니다. 두 번째는 데이터 이동입니다. 클러스터가 확장되고 새 노드가 추가되면 해당 노드의 데이터는 어디에서 오며, 클러스터가 축소되고 노드가 제거되면 해당 노드의 데이터는 어디로 이동합니까?

위 두 문제의 공통점은 데이터와 노드 간의 매핑 관계를 어떻게 기술하고 저장하는지 입니다. 문제의 진화는 데이터 위치가 키에 의해 결정되기 때문에 각 키와 클러스터의 모든 노드 사이의 연관을 설정해야 한다는 것입니다.

클러스터의 노드는 추가된 노드와 제거된 노드가 있지만 상대적으로 고정되어 있고 개수가 적습니다. 클러스터에 저장된 키는 엄청나게 많고, 완전히 무작위이고, 불규칙하고, 예측할 수 없으며 대부분 사소합니다.

이것은 대학과 모든 학생의 관계와 같습니다. 대학과 학생이 직접 연결된다면 분명 혼란스러울 것이다. 현실은 그들 사이에 여러 층이 추가되어 처음에는 학과가 있고 그 다음에는 전공이 있고 그 다음에는 성적이 있고 마지막으로 수업이 있다는 것입니다. 이 네 가지 수준의 매핑 후에는 관계가 훨씬 더 명확해집니다.

레이어를 추가한다고 해결되지 않는 문제는 없습니다. 이는 매우 중요한 결론입니다. 그렇다면 다른 레이어를 추가하세요. 컴퓨터에서도 마찬가지입니다.

Redis는 데이터와 노드 사이에 슬롯이라는 또 다른 레이어를 추가합니다. 슬롯은 주로 해싱과 관련되어 있기 때문에 해시 슬롯이라고도 합니다.

***가 되면 노드에는 슬롯이 배치되고 슬롯에는 데이터가 배치됩니다. 슬롯은 세분성 문제를 해결합니다. 이는 세분성을 더 크게 만드는 것과 동일하여 데이터 이동을 용이하게 합니다. 해시 기술은 매핑 문제를 해결하는 데 사용됩니다. 키의 해시 값을 사용하여 데이터 배포를 용이하게 하는 슬롯을 계산합니다.

공부 테이블에 책이 쌓여 있는데, 그 중 하나를 찾기가 매우 어렵습니다. 큰 수납함을 구입하여 제목 길이에 따라 책을 여러 수납함으로 분류한 다음 테이블 위에 올려 놓습니다.

이렇게 하면 테이블 위에 수납함이 있고, 수납박스 안에 책들이 들어있어요. 이렇게 하면 책을 쉽게 옮길 수 있습니다. 상자를 들고 이동하기만 하면 됩니다. 제목의 길이를 측정하고 해당 상자로 향하는 것만으로 필요한 책을 쉽게 찾을 수 있습니다.

사실 우리는 아무것도 하지 않고 상자 몇 개를 사서 일정한 규칙에 따라 상자에 책을 포장했습니다. 그런 단순한 움직임만으로도 원래 엉망이던 상황이 완전히 바뀌었습니다. 조금 마술적이지 않나요?

클러스터에는 0~16383까지 번호가 매겨진 16384개의 슬롯만 있을 수 있습니다. 이러한 슬롯은 클러스터의 모든 마스터 노드에 할당되며 할당 정책에 대한 요구 사항은 없습니다. 어떤 마스터 노드에 어떤 번호가 지정된 슬롯이 할당되는지 지정할 수 있습니다. 클러스터는 노드와 슬롯 간의 해당 관계를 기록합니다.

다음으로 키를 해시하고 결과를 16384로 나눈 후 나머지를 가져와서 키가 어느 슬롯에 들어갈지 결정합니다. 슬롯 = CRC16(키) % 16384.

슬롯 단위로 데이터를 이동하면 슬롯 수가 고정되어 있어 처리가 더 쉬워지므로 데이터 이동 문제가 해결됩니다.

해시 함수를 사용하여 키의 해시 값을 계산하여 해당 슬롯을 계산한 다음 슬롯과 클러스터에 저장된 노드 간의 매핑 관계를 사용하여 슬롯이 위치한 노드를 쿼리하고, 따라서 데이터와 노드가 매핑됩니다. 이러한 방식으로 데이터 할당 문제가 해결됩니다.

제가 말씀드리고 싶은 것은 보통 사람들은 다양한 기술만 배우게 된다는 것입니다. 전문가들은 어떻게 기술에서 벗어나 해결책이나 사고의 방향을 모색하는지에 더 관심을 갖는다는 것입니다. 당신은 대답을 원합니다.

클러스터의 명령 연산 선택

클라이언트가 클러스터의 한 노드와 링크만 설정하면 전체 클러스터의 모든 노드 정보를 얻을 수 있습니다. 또한 모든 해시 슬롯과 노드의 해당 관계 정보를 얻을 수 있습니다. 이 정보는 매우 유용하기 때문에 클라이언트에 캐시됩니다.

클라이언트는 어떤 노드에나 요청을 보낼 수 있으므로 키를 얻은 후 어느 노드에 요청을 보내야 할까요? 실제로는 키 집합과 노드 간의 이론적 매핑 관계를 이동하는 문제일 뿐입니다. 클라이언트에 클러스터링합니다.

그래서 클라이언트는 클러스터 측과 동일한 해시 함수를 구현해야 합니다. 먼저 키의 해시 값을 계산한 다음 나머지 16384를 가져옵니다. 이런 식으로 키에 해당하는 해시 슬롯을 찾고 클라이언트는 캐시를 이용하여 슬롯과 노드 사이의 해당 관계 정보를 이용하여 키에 해당하는 노드를 찾을 수 있습니다.

요청만 보내주세요. 또한, 다음에 키를 요청할 때 다시 계산할 필요 없이 해당 노드를 직접 가져올 수 있습니다.

클라이언트 캐시는 업데이트되지 않았지만 클러스터가 변경되어 이론과 현실의 괴리가 드러납니다. 해당 노드에서 요청한 키가 더 이상 해당 노드에 없을 가능성이 매우 높습니다. 이때 이 노드는 무엇을 해야 할까요?

이 노드는 실제로 키가 있는 노드로 이동하여 데이터를 가져와 클라이언트에 반환할 수도 있습니다. HTTP의 302 리디렉션과 유사하게 클라이언트가 다시 요청할 수 있도록 현재 키 정보가 있는 노드를 연결합니다.

이것은 사실 선택의 문제이자 철학적인 질문입니다. 결과적으로 Redis 클러스터는 후자를 선택했습니다. 따라서 노드는 자신이 소유한 키만 처리합니다. 소유하지 않은 키의 경우 리디렉션 오류, 즉 -MOVED 키 127.0.0.1:6381을 반환하고 클라이언트는 이 새 노드에 요청을 다시 보냅니다.

그래서 선택은 철학이자 지혜입니다. 이에 대해서는 나중에 자세히 설명합니다. 먼저 이 문제와 유사한 다른 상황을 살펴보겠습니다.

Redis에는 MGET과 같이 한 번에 여러 키를 가져올 수 있는 명령이 있습니다. 저는 이러한 다중 키 명령을 호출합니다. 이 다중 키 명령에 대한 요청이 노드로 전송됩니다. 여기에 잠재적인 문제가 있습니다. 즉, 이 명령의 여러 키가 동일한 노드에 있어야 하는지 궁금합니다. 두 가지 상황으로 나눌 수 있습니다. 동일한 노드에 여러 키가 없으면 노드는 리디렉션 오류만 반환할 수 있습니다. 그러나 여러 키가 여러 다른 노드에 있을 수 있으며 이때 반환되는 리디렉션 오류는 다음과 같습니다. 매우 특별합니다. 따라서 Redis 클러스터는 이 상황을 지원하지 않기로 결정합니다.

동일한 노드에 여러 개의 키가 있는 경우 이론상 문제는 없습니다. Redis 클러스터의 지원 여부는 Redis 버전에 따라 다르므로 직접 테스트해 보시기 바랍니다.

이 과정에서 우리는 매우 의미 있는 사실을 발견했습니다. 즉, 관련 키 세트를 동일한 노드에 매핑하는 것이 매우 필요하다는 것입니다. 이는 다중 키 명령을 통해 효율성을 높이고 여러 값을 한 번에 얻을 수 있다는 것입니다. .

그럼 문제는 이러한 키가 동일한 노드에 속하도록 이름을 지정하는 방법입니다. 먼저 해시 값을 계산한 다음 나머지를 가져와야 하는 것이 가능합니까? 물론 이것은 사실이 아닙니다. redis는 이미 우리를 위해 그것을 알아냈습니다.

간단히 말하면 두 개의 키가 동일한 노드에 있기를 원한다면 해시 값이 동일해야 합니다. 해시 값이 동일하려면 해시 함수에 전달되는 문자열이 동일해야 합니다. 두 개의 동일한 문자열만 전달하면 두 문자열은 동일한 키로 처리되며 후속 데이터가 이전 데이터를 덮어씁니다.

여기서 문제는 전체 키를 사용하여 해시 값을 계산한다는 점입니다. 이로 인해 해시 값 계산에 관련된 키와 문자열이 결합됩니다. 즉, 키와 문자열을 분리해야 합니다. 해시 값 계산에 관여합니다. 문자열은 서로 관련되어 있지만 다릅니다.

Redis는 키 해시 태그라고 하는 이 원칙을 기반으로 하는 솔루션을 제공합니다. 먼저 {user1000}.following, {user1000}.followers의 예를 살펴보겠습니다. 키에서 {와 } 사이의 문자열만 사용하여 해시 값 계산에 참여하는 트릭을 이미 보셨을 것입니다.

이렇게 하면 해시 값이 동일하고 동일한 노드에 속하도록 보장됩니다. 그러나 키는 서로 다르며 서로를 덮지 않습니다. 해시 태그를 사용하여 관련 키 세트를 연결하면 문제가 쉽고 원활하게 해결됩니다.

문제 해결은 뛰어난 기술과 알고리즘의 사용보다는 독창적인 창의성과 아이디어에 달려 있습니다. 작지만 강력한 Xiaoqiang입니다.

마지막으로 선택의 철학에 대해 이야기해보겠습니다. Redis의 주요 기능은 키-값 저장을 구현하고 일반적으로 사용되는 데이터 구조에 대한 액세스를 가능한 한 짧은 시간에 구현하고 이러한 데이터 구조에 대한 관련 작업을 수행하는 것입니다. 우리는 코어와 관련이 없거나 코어를 끌어내리는 모든 것을 약화시키거나 처리하지 않기로 선택합니다. 이는 코어가 단순하고 빠르며 안정적인지 확인하기 위해 수행됩니다.

사실 Redis는 폭과 깊이 앞에서 깊이를 선택했습니다. 따라서 노드는 자신이 소유하지 않은 키를 처리하지 않으며 클러스터는 여러 키에 대한 명령을 지원하지 않습니다. 이러한 방식으로 클라이언트는 신속하게 응답할 수 있고, 클러스터 내에서 대량의 데이터 전송 및 병합을 피할 수 있습니다.

단일 스레드 모델

Redis 클러스터의 각 노드에는 클라이언트가 보낸 모든 요청을 수락하고 실행하는 스레드가 하나만 있습니다. 기술적으로는 Linux epoll 기능을 사용하여 다중화 I/O를 사용하므로 하나의 스레드가 여러 소켓 연결을 관리할 수 있습니다.

또한 단일 스레드를 선택하는 이유는 다음과 같습니다.

1. Redis는 메모리에서 작동하며 매우 빠릅니다(10W+QPS)

2. 전체 시간은 주로 네트워크에서 소비됩니다

3. 멀티스레딩을 사용하는 경우 멀티스레딩 동기화가 필요하므로 구현이 복잡해집니다

4. 스레드 잠금 시간이 메모리 작업 시간을 초과합니다

5. 멀티스레딩으로 인해 컨텍스트 전환이 잦아집니다. 더 많은 CPU 시간

6. 또한 단일 스레드는 자연스럽게 원자 작업을 지원하며 단일 스레드 코드는 작성하기가 더 간단합니다

트랜잭션

트랜잭션은 여러 작업이 함께 묶이고 모두 실행된다는 것을 누구나 알고 있습니다( 성공) 또는 아무 것도 실행되지 않습니다(롤백). Redis도 트랜잭션을 지원하지만 원하는 것이 아닐 수도 있습니다.

Redis 트랜잭션은 트랜잭션 정의와 트랜잭션 실행의 두 단계로 나눌 수 있습니다. 트랜잭션을 시작한 후 실행할 명령을 모두 순서대로 추가합니다. 이는 트랜잭션을 정의합니다. 이때 exec 명령을 사용하여 트랜잭션을 실행하거나 폐기 명령을 사용하여 트랜잭션을 취소할 수 있습니다.

트랜잭션이 시작되기 전에 관심 있는 키가 다른 사람에 의해 조작되는 것을 원하지 않을 수 있습니다. 그런 다음 watch 명령을 사용하여 이러한 키가 실행을 시작하기 전에 다른 명령에 의해 작동되는 경우 트랜잭션이 발생하지 않도록 할 수 있습니다. 취소됩니다. unwatch 명령을 사용하여 이러한 키 모니터링을 취소할 수도 있습니다.

Redis 트랜잭션의 특징은 다음과 같습니다.

1. 트랜잭션을 시작하기 전에 오류가 발생하면 모든 명령이 실행되지 않습니다.

2. 일단 시작되면 모든 명령이 중단되지 않고 순차적으로 실행됩니다.

3 , 실행 중 오류가 발생하면 중단 없이 계속 실행됩니다

4. 실행 중 오류가 발생하면 롤백되지 않습니다

위 설명을 읽으면 이것이 맞는지 의문이 듭니다. 가능하다고 합니다. 분명히 이것은 우리가 일반적으로 트랜잭션으로 이해하는 것과 완전히 다릅니다. 왜냐하면 원자성이 보장되지도 않기 때문입니다. Redis는 롤백을 지원하지 않기 때문에 원자성을 지원하지 않으며, 이 기능을 지원하지 않는 데에는 이유가 있습니다.

롤백을 지원하지 않는 이유:

1. Redis는 명령의 부적절한 사용으로 인해 오류가 발생한다고 믿습니다.

2. Redis는 내부 구현을 간단하고 빠르게 유지하기 위해 이렇게 합니다.

3. 모든 문제를 해결하는 것은 아니다

ㅋㅋㅋ 이건 오버로드 조항이라 Redis 트랜잭션이 많이 사용되지 않은 것 같다

pipeline

클라이언트와 클러스터 사이의 상호작용 프로세스가 직렬화 블로킹, 즉 클라이언트가 명령을 보낸 후 두 번째 명령을 보내기 전에 응답이 돌아올 때까지 기다려야 합니다. 이는 왕복 시간입니다. 명령이 너무 많아서 하나씩 실행하면 속도가 매우 느려집니다.

Redis는 클라이언트가 서버의 응답을 기다리지 않고 한 번에 여러 명령을 보낼 수 있는 파이프라인 기술을 제공합니다. 모든 명령이 전송된 후 이러한 명령에 대한 모든 응답이 순서대로 수신됩니다. 이는 많은 시간을 크게 절약하고 효율성을 향상시킵니다.

또 다른 문제를 깨달을 만큼 똑똑합니까? 여러 명령은 여러 키입니다. 그러면 위에서 언급한 다중 키 작업이 아닌가요? 그러면 노드에서 이러한 여러 키가 동일하다는 것을 어떻게 보장할 수 있습니까? 하하, redis 클러스터가 다시 파이프라인 지원을 포기했습니다.

그러나 클라이언트 측에서 시뮬레이션할 수 있습니다. 즉, 여러 연결을 사용하여 동시에 여러 노드에 명령을 보낸 다음 모든 노드가 응답을 반환할 때까지 기다린 다음 순서대로 정렬하는 방식으로 시뮬레이션할 수 있습니다. 명령이 전송되고 이를 사용자 코드로 반환합니다. 아, 정말 곤란해요.

Protocol

Redis 프로토콜을 간략하게 이해하고 Redis 데이터 전송 형식을 알아보세요.

요청 전송 프로토콜:

*매개변수 수 CRLF$매개변수 1의 바이트 수 CRLF 매개변수 1의 데이터 CRLF...$매개변수 N의 바이트 수 CRLF 매개변수 N의 데이터 CRLF

예: SET 이름 lixinjie, 전송된 실제 데이터는 다음과 같습니다.

*3rn$3rnSETrn$4rnnamern$8rnlixinjiern

응답을 수락하는 프로토콜:

한 줄 응답, 첫 번째 바이트는 +

오류 메시지, 마지막 바이트는 -

정수, 첫 번째 바이트:

일괄 응답, 첫 번째 바이트는 $

다중 일괄 응답, 첫 번째 바이트는 *

예:

+OKrn

-ERR Operation againstrn

:1000rn

$6rnfoobarrn

*2rn$3rnfoorn$3rnbarrn

redis 프로토콜은 매우 간단하게 설계되었음을 알 수 있습니다.

위 내용은 Redis 지식 포인트를 분석하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제