Redis의 기술적인 포인트는 무엇인가요?

PHPz
풀어 주다: 2023-06-04 08:27:09
앞으로
1008명이 탐색했습니다.

1. Redis를 사용하는 이유

저자는 프로젝트에서 Redis를 사용할 때 성능과 동시성을 고려해야 한다고 믿습니다. 물론 Redis에는 분산 잠금 및 기타 기능을 수행할 수 있는 다른 기능도 있지만 분산 잠금과 같은 다른 기능만을 위한 것이라면 대신 사용할 수 있는 다른 미들웨어(예: Zookpeer 등)가 있으며 Redis는 사용할 필요는 없습니다.

따라서 이 질문은 주로 성능과 동시성의 두 가지 관점에서 답변됩니다.

1. 성능

아래 그림과 같이 실행해야 할 필요성이 발생하면 특히 긴 시간과 결과 SQL이 자주 변경되지 않는 경우 실행 결과를 캐시에 저장하는 것이 특히 적합합니다. 이러한 방식으로 후속 요청을 캐시에서 읽으므로 요청에 신속하게 응답할 수 있습니다.

Redis의 기술적인 포인트는 무엇인가요?

여담: 갑자기 신속한 응답의 기준에 대해 이야기하고 싶습니다. 사실 상호 작용 효과에 따라 이 응답 시간에 대한 고정된 기준은 없습니다. 누군가 나에게 이렇게 표현한 적이 있습니다. "이상적으로는 페이지 점프가 즉시 완료되어야 하고, 페이지 내 작업도 즉시 완료되어야 합니다." 또한 손가락을 한 번 튕기는 것 이상으로 시간이 많이 걸리는 작업에는 진행률 메시지가 있어야 하며 언제든지 일시 중지하거나 취소할 수 있어야 사용자에게 최상의 경험을 제공할 수 있습니다. ”

그럼 한 순간, 한 순간, 아니면 손가락 튕기기는 얼마나 되나요?

"마하승하비나야" 기록에 따르면, 한 순간은 한 생각이고, 스무 생각은 한 순간이고, 스무 순간은 한 번 치는 것입니다. 손가락을 스무번 치면 한라가 한 순간이고, 스물루가 한 순간이고, 낮과 밤이 삼십 순간입니다.

그래서, 한 순간은 0.36초이고, 한 순간은 입니다. 0.018초, 손가락 하나의 길이는 7.2초입니다.

2. 동시성

동시성이 높으면 그림과 같이 데이터베이스에 직접 액세스하려는 모든 요청이 데이터베이스 연결 예외를 발생시킵니다. 데이터베이스에 대한 직접 액세스를 피하기 위해 이 경우 버퍼링을 위해 Redis를 사용할 수 있습니다.

Redis의 기술적인 포인트는 무엇인가요?

2. Redis 사용의 단점은 무엇입니까?

모두가 오랫동안 Redis를 사용해 왔습니다. 기본적으로 Redis를 사용하면 몇 가지 문제에 직면하게 됩니다. 가장 일반적인 문제는 주로 다음 네 가지 측면입니다.

1. 데이터베이스 2. 캐시 문제

4. 캐시 동시성 경쟁 질문

저자는 개인적으로 이 네 가지 문제가 프로젝트에서 더 흔하다고 생각합니다

.

3. 단일 스레드 Redis가 왜 그렇게 빠른지

이 질문은 실제로 Redis의 내부 메커니즘에 대한 조사입니다. 실제로 많은 사람들이 Redis가 사용하는 것을 인식하지 못합니다. 따라서 이 질문은 다음 세 가지 사항을 중심으로 검토해야 합니다. 블로킹 I/O 멀티플렉싱 메커니즘I/O에 대해 더 자세히 논의하겠습니다. 멀티플렉싱 메커니즘은 일반 사람들이 그 의미를 이해하기에는 너무 인기가 있기 때문입니다. 예를 들어 Xiaoqu는 S시에 택배 매장을 열고 내부 업무를 담당했습니다. - 도시 특급 배송. 처음에는 Xiaoqu가 많은 택배 직원을 고용했지만 나중에는 자동차를 구입해야만 특급 배송을 운영할 수 있는 자금을 확보할 수 있다는 사실을 알게 되었습니다.

비즈니스 방법 1: 고객이 배송할 때마다. Xiaoqu는 택배기사가 이를 지켜보도록 하고 택배기사가 직접 운전하여 택배를 배송하게 됩니다. Xiaoqu는 천천히 이 비즈니스 방법에 많은 문제가 있음을 발견했습니다. 대부분의 택배기사는 유휴 상태였습니다. 차를 잡은 사람은 누구나 택배로 배달할 수 있습니다.

특급 배송이 증가함에 따라 택배 매장이 점점 더 많아지고 있음을 발견했습니다. 새로운 택배를 고용할 방법이 없습니다. 택배원 간의 조정에는 시간이 많이 걸립니다. 위의 단점을 바탕으로 Xiaoqu는 경험을 통해 다음과 같은 비즈니스 방법을 제안했습니다. ↓

비즈니스 방법 2 :

Xiaoqu는 택배기사 한 명만 고용하고, 고객이 보낸 특급 배송물을 목적지에 따라 분류하여 한 곳에 깔끔하게 정리합니다. 마침내 택배기사가 순서대로 택배기사를 픽업하고, 택배기사를 몰아냅니다. , 그리고 다음 택배를 받으러 돌아갑니다.

위의 두 가지 비즈니스 방법을 비교하면 두 번째 방법이 더 효율적이고 더 나은 것이 분명합니까? 위의 비유에서:

1. 각 택배 → 각 스레드

2. 각 택배 → 각 소켓(I/O 스트림)

3. 특급 배송 위치 → 소켓의 다양한 상태

4. 고객의 특급 배송 요청 → 클라이언트 요청

5. Xiaoqu의 비즈니스 방법 → ​​서버에서 실행되는 코드

6. 자동차 → CPU 코어 수

그래서 우리는 다음과 같은 결론을 얻었습니다.

1. 각 I/O 스트림(express)은 새로운 스레드(courier)에 의해 관리되는 전통적인 동시성 모델입니다.

2. 두 번째 관리 방법은 I/O 다중화입니다. 택배사는 각 I/O 흐름의 상태를 추적하여 여러 I/O 흐름을 관리합니다. 이는 각 패키지를 배송할 사람이 한 명뿐이고 각 패키지의 배송 상태를 알아야 하는 택배사와 유사합니다.

다음은 그림과 같이 실제 Redis 스레드 모델에 비유한 것입니다.

Redis의 기술적인 포인트는 무엇인가요?

위 그림을 참조하면 간단히 말하면 Redis 클라이언트가 작동하면 다른 이벤트로 소켓이 생성됩니다. 유형. 서버 측에는 이를 대기열에 넣는 I/O 다중화 프로그램이 있습니다. 그런 다음 파일 이벤트 디스패처는 이를 대기열에서 차례로 가져와서 다른 이벤트 프로세서로 전달합니다.

이 I/O 다중화 메커니즘을 위해 Redis는 Select, Epoll, Evport 및 Kqueue와 같은 다중화 기능 라이브러리도 제공한다는 점에 유의해야 합니다.

4. Redis 데이터 유형 및 해당 사용 시나리오

이 질문을 보면 매우 기본적이라고 생각하시나요? 사실 나도 그렇게 생각한다. 그러나 인터뷰 경험에 따르면 적어도 80%의 사람들은 이 질문에 답하지 못한다. 프로젝트에 사용한 후에는 암기하기보다는 비유적으로 암기하여 더 깊은 이해를 얻는 것이 좋습니다. 기본적으로 자격을 갖춘 프로그래머는 5가지 유형을 사용합니다.

1, String

실제로 이에 대해 말할 것은 없습니다. 가장 일반적인 Set/Get 작업의 경우 값은 문자열이거나 숫자일 수 있습니다. , 일반적으로 복잡한 계산 기능을 일부 캐싱합니다.

2. Hash

여기의 값은 구조화된 객체를 포함하는 변수로, 내부의 특정 필드를 편리하게 조작할 수 있습니다. 작성자가 Single Sign-On을 수행할 때 이 데이터 구조를 사용하여 사용자 정보를 저장하고 CookieId를 키로 사용하며 캐시 만료 시간을 30분으로 설정하여 세션과 유사한 효과를 매우 잘 시뮬레이션할 수 있습니다.

3. List

List의 데이터 구조를 이용하면 간단한 메시지 큐 기능을 수행할 수 있습니다. 또한 Redis의 Lrange 명령을 사용하여 페이징 기능을 구현할 수도 있는데, 이는 성능이 뛰어나고 좋은 사용자 경험을 제공할 수 있습니다.

4. Set

Set은 고유한 값의 집합을 잔뜩 쌓아두기 때문에 전역 중복 제거 기능을 수행할 수 있습니다.

중복 제거를 위해 JVM과 함께 제공되는 세트를 사용하는 것은 어떨까요? 우리 시스템은 일반적으로 클러스터로 배포되기 때문에 JVM과 함께 제공되는 Set을 사용하는 것이 번거롭습니다. 전역 중복 제거를 위해 공용 서비스를 만들어야 합니까? 문제가 너무 많아요.

또한 교집합, 합집합, 차이 등의 연산을 이용하여 공통선호도, 전체선호도, 나만의 고유선호도를 계산할 수 있습니다.

5. Sorted Set

Score 매개변수를 세트의 요소에 할당하면 Sorted Set에서 Score에 따라 요소를 정렬할 수 있습니다. 순위신청을 하고 TOP N 연산을 수행할 수 있습니다. 또한 정렬된 집합을 사용하여 지연된 작업을 수행할 수도 있습니다. 마지막 응용 프로그램은 범위 검색을 수행하는 것입니다.

5. Redis의 만료 전략 및 메모리 제거 메커니즘

이 질문의 중요성은 자명하며, Redis가 올바르게 적용되었는지 여부를 밝힐 수 있습니다. 예를 들어 Redis가 5G의 데이터만 저장할 수 있는데 10G를 쓰면 5G의 데이터가 삭제됩니다. 어떻게 삭제됐나요? 이 문제에 대해 생각해 보셨나요? 또한 데이터에 만료 시간이 설정되어 있지만 만료 시간이 지났을 때에도 여전히 메모리 사용량이 상대적으로 높습니다. 그 이유를 생각해 보셨나요?

Redis는 일반 삭제 + 게으른 삭제 전략을 채택하고 있습니다.

예약 삭제 전략을 사용하는 것은 어떨까요?

정기 삭제, 타이머를 사용하여 키를 모니터링하고 만료되면 자동으로 삭제됩니다. 메모리는 제때 해제되지만 CPU 리소스를 많이 소모합니다. 대규모 동시 요청의 경우 CPU는 키를 삭제하는 대신 요청을 처리하는 데 시간을 사용해야 하므로 이 전략은 채택되지 않습니다.

일반 삭제 + 지연 삭제는 어떻게 작동하나요?

정기 삭제, Redis는 기본적으로 100ms마다 만료된 키가 있는지 확인하고 만료된 키가 있으면 삭제합니다. Redis는 100ms마다 모든 키를 확인하지 않고 무작위로 선택하여 확인한다는 점에 유의해야 합니다(모든 키를 100ms마다 확인하면 Redis는 중단되지 않습니다). 따라서 주기적인 삭제 전략만 채택하면 시간이 끝날 때까지 많은 키가 삭제되지 않습니다.

그래서 게으른 삭제가 유용합니다. 즉, 키를 받으면 Redis는 이 키에 만료 시간이 설정되어 있는지 확인합니다. 만료되면 이때 삭제됩니다.

일반삭제 + 지연삭제를 하면 다른 문제는 없나요?

아니요, 일반 삭제로 키가 삭제되지 않는 경우입니다. 그런 다음 키를 제때 요청하지 않았으므로 지연 삭제가 적용되지 않았습니다. Redis의 메모리가 지속적으로 증가하는 것을 방지하려면 메모리 제거 메커니즘을 활성화해야 합니다.

Redis.conf에는 구성 라인이 있습니다:

# maxmemory-policy 휘발성-lru

이 구성에는 메모리 제거 전략이 탑재되어 있습니다:

Noeviction: 메모리가 수용하기에 충분하지 않은 경우 새로 작성된 데이터, 새로운 쓰기 작업은 오류를 보고합니다. 누구도 사용해서는 안 됩니다.

Allkeys-lru: 새로 작성된 데이터를 수용할 만큼 메모리가 충분하지 않은 경우 키 공간에서 가장 최근에 사용된 키를 제거합니다. 권장합니다. 현재 프로젝트에서 이것을 사용하고 있습니다.

Allkeys-random: 새로 작성된 데이터를 수용할 만큼 메모리가 충분하지 않으면 키 공간에서 키가 무작위로 제거되며 누구도 이를 사용해서는 안 됩니다.

Volatile-lru:

새로 작성된 데이터를 수용할 만큼 메모리가 충분하지 않은 경우 만료 시간이 설정된 키 공간에서 가장 최근에 사용된 키를 제거합니다. 이 상황은 일반적으로 Redis가 캐시와 영구 저장소로 사용될 때 사용됩니다. 권장하지 않음

Volatile-random:

새로 작성된 데이터를 수용할 만큼 메모리가 부족하면 만료 시간이 설정된 키 공간에서 키가 무작위로 제거됩니다. 여전히 권장되지 않습니다.

Volatile-ttl:

새로 작성된 데이터를 수용할 만큼 메모리가 충분하지 않은 경우 만료 시간이 설정된 키 공간에서 만료 시간이 더 빠른 키가 먼저 제거됩니다. 권장되지 않습니다. PS: Expire Key가 설정되지 않았고 전제 조건이 충족되지 않은 경우 Volatile-lru, Volatile-random 및 Volatile-ttl 전략의 동작은 기본적으로 Noeviction과 동일합니다(삭제되지 않음).

6. Redis와 데이터베이스 간의 이중 쓰기 일관성 문제

일관성 문제는 일반적인 분산 문제로 최종 일관성과 강력한 일관성으로 더 나눌 수 있습니다. 데이터베이스와 캐시가 이중으로 작성되면 필연적으로 불일치가 발생합니다. 이 질문에 답하려면 먼저 데이터에 대한 강력한 일관성 요구 사항이 있으면 캐시를 배치할 수 없다는 전제를 이해해야 합니다. 우리가 하는 모든 일은 최종 일관성만 보장할 수 있습니다.

저희가 제안한 솔루션은 불일치 가능성을 줄일 수 있을 뿐, 완전히 제거할 수는 없습니다. 따라서 강력한 일관성 요구 사항이 있는 데이터는 캐시할 수 없습니다.

"분산 데이터베이스 및 캐시 이중 쓰기 일관성 솔루션"

은 자세한 분석을 제공합니다. 다음은 간략한 설명입니다. 먼저 올바른 업데이트 전략을 채택하고 먼저 데이터베이스를 업데이트한 다음 캐시를 삭제합니다. 캐시 삭제 실패 문제가 발생할 수 있으므로 메시지 큐를 사용하는 등의 보상 조치를 제공하면 됩니다.

7. 캐시 침투 및 캐시 눈사태 문제 처리

일반적으로 중소 규모의 기존 소프트웨어 회사에서는 캐시 침투 및 캐시 눈사태 문제가 거의 발생하지 않습니다. 수백만 개의 트래픽을 처리하려면 다음 두 가지 문제를 신중하게 고려해야 합니다.

1. 캐시 침투 처리

캐시 침투, 즉 해커가 의도적으로 존재하지 않는 콘텐츠를 요청합니다. 캐시 데이터로 인해 모든 요청이 데이터베이스로 전송되어 데이터베이스 연결이 비정상적으로 발생합니다.

해결책:

뮤텍스 잠금을 사용하세요. 캐시가 실패하면 먼저 잠금을 얻으세요. 잠금을 얻으면 데이터베이스를 요청하세요. 잠금을 얻지 못하면 잠시 잠을 자게 됩니다. 다시 시도하세요.

1. Key가 값을 가져오는지 여부에 관계없이 비동기 업데이트 전략을 사용하면 직접 반환됩니다. 캐시 만료 시간은 값 값에 유지됩니다. 캐시가 만료되면 데이터베이스를 읽고 캐시를 업데이트하기 위해 스레드가 비동기적으로 시작됩니다. 캐시 준비 작업이 필요합니다(프로젝트를 시작하기 전에 캐시를 로드하세요).

2. 요청을 신속하게 판단할 수 있는 방법을 제공합니다. 예를 들어 Bloom 필터를 사용하여 일련의 합법적이고 유효한 키를 내부적으로 유지하고 요청에 포함된 키가 합법적이고 유효한지 여부를 신속하게 판단합니다. 유효하며, 합법적이지 않은 경우 직접 반환됩니다.

2. 캐시 눈사태 대처법

캐시 눈사태, 즉 넓은 영역에서 동시에 캐시가 실패하는 경우, 또 다른 요청의 물결이 들어오고, 그 결과 요청이 모두 데이터베이스로 전송되어 데이터베이스 연결 예외가 발생합니다. 해결책:

1. 집단적 실패를 방지하기 위해 캐시 만료 시간에 임의의 값을 추가합니다.

2. 뮤텍스 잠금을 사용하지만 이 솔루션의 처리량이 크게 떨어졌습니다.

3. 캐시 A와 캐시 B라는 두 개의 캐시가 있습니다. 캐시 A의 만료 시간은 20분이고, 캐시 B의 만료 시간은 없습니다. 캐시 예열 작업은 자체적으로 수행됩니다.

그런 다음 다음 사항을 분석합니다.

a. 캐시 A에서 데이터베이스를 읽고, 있는 경우 직접 반환합니다.

b A에 데이터가 없으면 B에서 직접 데이터를 읽고, 다시 반환합니다. 업데이트 스레드를 비동기적으로 시작합니다. ;

c. 업데이트 스레드는 캐시 A와 캐시 B를 동시에 업데이트합니다.

8. 키를 놓고 경쟁하는 Redis 동시성 문제를 해결하는 방법

이 문제는 대략 여러 하위 시스템이 동시에 키를 설정한다는 것입니다. 이 경우 Redis 트랜잭션 메커니즘을 사용할 때 주의해야 합니다. 제가 사전에 바이두에서 검색한 결과에 따르면 대부분의 사람들이 이 방법을 추천합니다. 하지만 Redis의 트랜잭션 메커니즘을 사용하는 것은 권장하지 않습니다. 프로덕션 환경에서는 주로 Redis 클러스터를 사용하고 데이터 샤딩을 수행합니다. 트랜잭션에 여러 키 작업이 포함된 경우 이러한 키가 반드시 동일한 Redis-Server에 저장될 필요는 없습니다. 따라서 Redis의 트랜잭션 메커니즘은 매우 쓸모가 없습니다. 해결 방법은 다음과 같습니다.

이 Key 작업의 순서가 필요하지 않은 경우

이 경우 분산 잠금 장치를 준비하면 모두가 잠금 장치를 잡고 잠금 장치를 잡은 후 Set 작업을 수행하면 됩니다. 비교적 간단합니다.

이 키 조작에 순서가 필요한 경우

Key1이 있다고 가정해 보겠습니다. 시스템 A는 Key1을 ValueA로 설정해야 하고, 시스템 B는 Key1을 ValueB로 설정해야 하며, 시스템 C는 Key1을 ValueC로 설정해야 합니다. Key1의 값은 ValueA→ValueB→ValueC의 순서로 변할 것으로 예상된다. 이때 데이터베이스에 데이터를 쓸 때 타임스탬프를 저장해야 합니다. 타임스탬프는 다음과 같다고 가정합니다.

1. 시스템 A 키 1 {ValueA 3:00}

2. 시스템 B 키 1 {ValueB 3:05}

3.

그런 다음 시스템 B가 먼저 잠금을 잡고 Key1을 {ValueB 3:05}로 설정한다고 가정합니다. 시스템 A가 잠금을 잡고 ValueA의 타임스탬프가 캐시의 타임스탬프보다 이전임을 발견하면 Set 작업이 수행되지 않습니다. 등등.

위 내용은 Redis의 기술적인 포인트는 무엇인가요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:yisu.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿