>  기사  >  데이터 베이스  >  Redis의 8가지 고전적인 문제는 무엇입니까?

Redis의 8가지 고전적인 문제는 무엇입니까?

王林
王林앞으로
2023-06-03 14:44:481243검색

1. Redis를 사용하는 이유

블로거는 프로젝트에서 Redis를 사용할 때 가장 중요한 고려 사항은 성능과 동시성이라고 믿습니다. 물론 Redis에는 분산 잠금 등 다른 기능도 있지만 분산 잠금 등 다른 기능만을 위한 것이라면 대신 다른 미들웨어(zookpeer 등)가 있으므로 굳이 Redis를 사용할 필요는 없다. 따라서 이 질문은 주로 성능과 동시성이라는 두 가지 관점에서 답변됩니다.

답변: 아래와 같이 2가지 점으로 나뉜다

(1) Performance

실행 시간이 길고 결과가 자주 바뀌지 않는 SQL을 만나면 결과를 다음 폴더에 저장하는 것이 좋습니다. 은닉처. 이러한 방식으로 후속 요청은 캐시에서 읽혀지므로 요청에 신속하게 응답할 수 있습니다.

Redis의 8가지 고전적인 문제는 무엇입니까?

여담: 갑자기 이런 신속한 대응의 기준에 대해 이야기하고 싶습니다. 실제로 상호작용 효과에 따라 이 응답 시간에 대한 고정된 기준은 없습니다. 그러나 누군가 나에게 이렇게 말한 적이 있습니다. "이상적인 세상에서는 페이지 이동이 즉시 해결되어야 하고, 페이지 내 작업도 즉시 해결되어야 합니다. 최고의 사용자 경험을 제공하려면 1초의 시간이 제공되어야 진행 상황이 표시되고 언제든지 정지 또는 취소가 가능합니다. "

그러면 순간, 순간, 손가락 찰칵 소리의 시간은 얼마나 되나요?

마하상가율(Maha Sangha Vinaya) 기록에 따르면

한 순간은 하나의 생각이고, 스무 개의 생각은 하나의 순간이고, 스무 개의 순간은 한 번의 손가락 튕김이며, 스무 번의 손가락 찰칵은 하나의 뤄수, 스무 개의 뤄수는 하나의 순간입니다 , 하루 낮과 밤의 순간이 있습니다.

그래서 신중하게 계산한 결과 1순간은 0.36초, 1순간은 0.018초, 손가락 찰칵 소리의 길이는 7.2초입니다.

(2) 동시성

아래 그림과 같이 대규모 동시성의 경우 모든 요청이 데이터베이스에 직접 액세스하며 데이터베이스에는 연결 예외가 발생합니다. 이 경우 요청이 데이터베이스에 직접 액세스하는 대신 먼저 Redis에 액세스하도록 Redis 버퍼링 작업을 사용해야 합니다.

Redis의 8가지 고전적인 문제는 무엇입니까?

2. Redis를 사용하면 어떤 단점이 있나요?

분석: 모두가 오랫동안 Redis를 사용해 왔으며 이 문제는 기본적으로 Redis를 사용할 때 몇 가지 문제에 직면하게 된다는 점을 이해해야 합니다. 몇 가지 일반적인 것들만.

답변: 주로 네 가지 질문입니다.

(1) 캐시 및 데이터베이스 이중 쓰기 일관성 문제

(2) 캐시 눈사태 문제

(3) 캐시 분석 문제

(4 ) 캐시 동시성 경쟁 문제

개인적으로는 이 네 가지 문제가 프로젝트에서 비교적 일반적이라고 생각합니다. 구체적인 해결책은 나중에 제공됩니다.

참조: "캐시 사태, 캐시 침투, 캐시 워밍업, 캐시 업데이트, 캐시 다운그레이드 및 기타 문제!" 》

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

분석: 이 질문은 실제로 Redis의 내부 메커니즘에 대한 조사입니다. 블로거의 인터뷰 경험에 따르면 실제로 많은 사람들이 Redis의 단일 스레드 작업 모델을 이해하지 못합니다. 따라서 이 문제는 여전히 검토되어야 합니다.

답변: 주로 다음 세 가지 사항

(1) 순수 메모리 작업

(2) 단일 스레드 작업, 빈번한 컨텍스트 전환 방지

(3) 비차단 I/O 다중화 메커니즘 사용

여담 : 이제 I/O 다중화 메커니즘에 대해 자세히 이야기하고 싶습니다. 이 용어는 너무 유명해서 대부분의 사람들이 그 의미를 이해하지 못하기 때문입니다. 블로거는 다음과 같이 비유했습니다. Xiaoqu는 City S에 특급 매장을 열고 도시의 특급 배송 서비스를 담당했습니다. 제한된 자금으로 인해 Xiaoqu는 처음에는 택배 그룹을 고용했지만 나중에 자금이 부족하여 특급 배송을 위한 자동차만 구입할 수 있음을 발견했습니다.

비즈니스 방법 1

고객이 택배를 배달할 때마다 Xiaoqu는 택배를 배정하여 이를 감시하고, 그러면 택배가 직접 운전하여 택배를 배달합니다. 천천히 Xiaoqu는 이 사업 방법에서 다음과 같은 문제점을 발견했습니다

  • 수십 명의 택배원이 기본적으로 자동차를 집는 데 시간을 보냈습니다. 대부분의 택배원은 차를 집은 사람이 누구든 특급 배송을 할 수 있습니다

  • 배송, 택배기사가 점점 많아지고 있습니다. Xiaoqu는 특급 배송 매장이 점점 더 혼잡해지고 있으며 새로운 택배사를 고용할 방법이 없다는 것을 발견했습니다

  • 택배사 중에서 택배사 간의 조정에는 많은 시간이 걸립니다

위의 단점을 바탕으로 Xiaoqu는 고통스러운 경험을 통해 다음과 같은 비즈니스 방법을 제안했습니다.

비즈니스 방법 2

Xiaoqu는 택배 기사를 한 명만 고용합니다. Xiaoqu는 배송 위치에 따라 고객이 보낸 특급 배송을 표시하고 같은 장소에 배치합니다. 결국 택배기사님이 한 번에 하나씩 택배를 수거한 후 차를 몰고 가서 택배를 배달하고, 배송이 끝난 뒤 다음 택배를 찾으러 돌아왔습니다.

비교

위의 두 가지 사업 방식을 비교해 보면, 두 번째 방법이 더 효율적이고 더 좋은 것은 분명한가요? 위의 비유에서:

  • 모든 택배 ------> 모든 스레드

  • 모든 택배 ------- ---- --------->각 소켓(I/O 스트림)

  • 빠른 배송 위치--------------->소켓 다양한 상태

  • 고객 특급 배송 요청--------------->고객의 요청

  • Xiaoqu의 비즈니스 방법---------------> ;코드 서버에서 실행

  • 자동차--------->CPU 코어 수

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

1. 첫 번째 비즈니스 방법은 전통적인 동시성 모델입니다. 각 I/O 스트림(express)은 새로운 스레드(courier)에 의해 관리됩니다.

2. 두 번째 관리 방법은 I/O 다중화입니다. 각 I/O 스트림의 상태(각 택배사의 배송 위치)를 추적하여 여러 I/O 스트림을 관리하는 단일 스레드(택배사)만 있습니다.

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

Redis의 8가지 고전적인 문제는 무엇입니까?

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

이 I/O 다중화 메커니즘을 위해 redis는 select, epoll, evport, kqueue 등과 같은 다중화 기능 라이브러리도 제공한다는 점에 유의해야 합니다. 이에 대해 직접 배울 수 있습니다.

4. Redis 데이터 유형 및 각 데이터 유형의 사용 시나리오

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

답변: 총 5가지 유형이 있습니다

(1) 문자열

이것은 실제로 매우 일반적이며 가장 기본적인 가져오기/설정 작업과 관련됩니다. 값은 문자열 또는 숫자일 수 있습니다. 일반적으로 일부 복잡한 계산 기능이 캐시됩니다.

(2) hash

여기의 값은 구조화된 객체를 저장하며, 그 안에 특정 필드를 조작하는 것이 더 편리합니다. 블로거는 Single Sign-On을 수행할 때 이 데이터 구조를 사용하여 사용자 정보를 저장하고, cookieId를 키로 사용하고, 캐시 만료 시간을 30분으로 설정하므로 세션과 유사한 효과를 매우 잘 시뮬레이션할 수 있습니다.

(3) list

List의 데이터 구조를 이용하면 간단한 메시지 큐 기능을 수행할 수 있습니다. 또한 lrange 명령을 사용하여 Redis 기반 페이징 기능을 구현할 수도 있습니다. 이 방법은 뛰어난 성능과 사용자 경험을 제공합니다.

(4)set

세트는 고유한 값의 집합이기 때문입니다. 따라서 전역 중복 제거 기능을 구현할 수 있습니다. 중복 제거를 위해 JVM과 함께 제공되는 세트를 사용하는 것은 어떻습니까? 우리 시스템은 일반적으로 클러스터로 배포되기 때문에 JVM과 함께 제공되는 Set을 사용하는 것이 번거롭습니다. 단지 전역 중복 제거를 수행하기 위해 공용 서비스를 설정하는 것이 너무 번거롭습니까?

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

(5) sorted set

sorted set에는 추가 가중치 매개변수 점수가 있으며, 세트의 요소는 점수에 따라 정렬될 수 있습니다. 순위신청을 하고 TOP N 연산을 수행할 수 있습니다. 또한, "분산 지연 작업 방식 분석"이라는 기사에서는 정렬 집합을 사용하여 지연 작업을 구현할 수 있다고 언급하고 있습니다. 마지막 응용 프로그램은 범위 검색을 수행하는 것입니다.

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

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

답변:

Redis는 일반 삭제 + 게으른 삭제 전략을 채택합니다.

예약 삭제 전략을 사용하면 어떨까요?

예약 삭제, 타이머를 사용하여 키를 모니터링하고 만료되면 자동으로 삭제합니다. 메모리는 제때 해제되지만 CPU 리소스를 많이 소모합니다. 동시 요청이 많은 경우 CPU는 키 값 삭제 작업보다 요청 처리에 집중해야 하므로 이 전략 채택을 포기했습니다

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

주기적 삭제, redis 기본값 100ms마다 확인 만료된 키가 있는지 확인하세요. 만료된 키가 있으면 삭제하세요. Redis는 100ms마다 모든 키를 확인하지 않지만 검사를 위해 무작위로 선택한다는 점에 유의해야 합니다(모든 키를 100ms마다 확인하면 Redis가 중단되지 않습니까?). 주기적 삭제 전략만 사용하는 경우 만료 시간 이후에도 많은 키가 삭제되지 않습니다.

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

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

아니요, 정기삭제 시 키가 삭제되지 않는 경우입니다. 그런 다음 키를 즉시 요청하지 않았으므로 지연 삭제가 적용되지 않았습니다. 이런 식으로 Redis의 메모리는 점점 더 높아질 것입니다. 그런 다음 메모리 제거 메커니즘을 채택해야 합니다.

redis.conf에 구성 줄이 있습니다

# maxmemory-policy 휘발성-lru

이 구성은 메모리 제거 전략으로 구성됩니다(뭐, 아직 구성하지 않았나요? 반성하세요)

1) noeviction: 메모리가 새로 작성된 데이터를 수용할 공간이 충분하지 않으면 새 쓰기 작업에서 오류를 보고합니다. 누구도 그것을 사용해서는 안 됩니다.

새 데이터를 저장할 메모리 공간이 부족한 경우 allkeys-lru 알고리즘은 키 공간에서 가장 최근에 사용된 키를 제거합니다. 권장되며 현재 프로젝트에서 사용됩니다.

3) allkeys-random: 새로 작성된 데이터를 수용할 만큼 메모리가 충분하지 않은 경우 키 공간에서 키가 무작위로 제거됩니다. 누구도 사용하지 말아야 합니다. 삭제하고 싶지 않다면 최소한 키를 사용하여 무작위로 삭제하세요.

4) 휘발성-lru: 새로 작성된 데이터를 수용할 만큼 메모리가 충분하지 않은 경우 만료 시간이 설정된 키 공간에서 가장 최근에 사용된 키를 제거합니다. 일반적으로 이 방법은 redis가 캐시와 영구 저장소로 모두 사용되는 경우에만 사용됩니다. 권장하지 않음

5) 휘발성-랜덤: 새로 작성된 데이터를 수용할 만큼 메모리가 부족한 경우 만료 시간이 설정된 키 공간에서 키가 무작위로 제거됩니다. 여전히 권장되지 않음

6) 휘발성-ttl: 새로 작성된 데이터를 수용할 만큼 메모리가 충분하지 않은 경우 만료 시간이 설정된 키 공간에서 만료 시간이 더 빠른 키가 먼저 제거됩니다. 권장되지 않음

ps: 만료 키가 설정되지 않고 전제 조건이 충족되지 않으면 휘발성-lru, 휘발성-랜덤 및 휘발성-ttl 전략의 동작은 기본적으로 noeviction(삭제 없음)과 동일합니다.

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

분산 시스템에서 일관성 문제는 일반적인 문제입니다. 이 문제는 최종 일관성과 강력한 일관성으로 더 구분될 수 있습니다. 데이터베이스와 캐시가 이중으로 기록되면 필연적으로 불일치가 발생합니다. 이 질문에 답하려면 먼저 전제를 이해해야 합니다. 즉, 데이터에 대한 강력한 일관성 요구 사항이 있으면 캐시할 수 없습니다. 우리가 하는 모든 일은 최종 일관성만 보장할 수 있습니다. 우리가 제안한 솔루션은 실제로 일관되지 않은 이벤트의 확률을 줄일 수 있을 뿐 완전히 제거할 수는 없습니다. 따라서 강력한 일관성 요구 사항이 있는 데이터는 캐시할 수 없습니다.

"분산 데이터베이스 및 캐시 이중 쓰기 일관성 기법 분석" 기사의 자세한 분석에 대해 간략하게 소개합니다. 먼저 올바른 업데이트 전략을 채택하고 데이터베이스를 먼저 업데이트한 다음 캐시를 삭제하세요. 캐시 삭제에 실패할 경우를 대비하여 메시지 큐를 활용하는 등의 백업 수단을 제공합니다.

7. 캐시 침투 및 캐시 사태 문제를 처리하는 방법

중소 규모의 기존 소프트웨어 회사는 솔직히 이 두 가지 문제에 거의 직면하지 않습니다. 대규모 동시 프로젝트가 있는 경우 트래픽은 약 수백만 달러에 이릅니다. 이 두 가지 문제를 깊이 생각해 보아야 합니다.

답변: 아래와 같이

캐시 침투 즉, 해커가 의도적으로 캐시에 존재하지 않는 데이터를 요청하여 모든 요청이 데이터베이스로 전송되어 데이터베이스 연결이 비정상적으로 되는 현상입니다.

해결책:

캐시가 실패하면 뮤텍스 잠금을 사용하여 먼저 잠금을 획득한 다음 잠금이 획득되면 데이터베이스를 요청하세요. 잠금을 얻지 못하면 일정 시간 동안 잠자기 상태가 된 후 다시 시도합니다

(2) 비동기 업데이트 전략을 채택하고 키에 값이 있는지 여부에 관계없이 직접 반환합니다. 값 값에 캐시 만료 시간을 저장합니다. 캐시가 만료되면 스레드가 비동기적으로 시작되어 데이터베이스를 읽고 캐시를 업데이트합니다. 캐시 예열(프로젝트 시작 전 캐시 로딩) 작업이 필요합니다.

요청이 유효한지 빠르게 확인할 수 있는 차단 메커니즘을 제공하세요. 예를 들어 Bloom 필터를 사용하여 일련의 합법적이고 유효한 키를 내부적으로 유지 관리합니다. 요청에 포함된 키가 합법적이고 유효한지 신속하게 확인합니다. 불법이라면 직접 반납하세요.

Cache Avalanche, 즉 넓은 영역에서 캐시가 동시에 실패하는 경우 또 다른 요청의 물결이 발생하고 결과적으로 요청이 모두 데이터베이스로 전송되어 데이터베이스 연결 예외가 발생합니다.

해결책:

(1) 집단적 실패를 방지하려면 캐시 만료 시간에 임의의 값을 추가합니다.

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

(3) 더블 캐시. 캐시 A와 캐시 B라는 두 개의 캐시가 있습니다. 캐시 A의 만료 시간은 20분이고, 캐시 B의 만료 시간은 없습니다. 캐시 준비 작업을 직접 수행하십시오. 그런 다음 다음 사항을 분석합니다.

  • 캐시 A에서 데이터베이스를 읽고, 있으면 직접 반환합니다.

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

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

8. Redis

에서 동시 키 경쟁 문제를 해결하는 방법

분석: 이 문제는 대략 동시에 키를 설정하는 여러 하위 시스템이 있다는 것입니다. 이때 우리가 주의해야 할 점은 무엇입니까? 그것에 대해 생각해 본 적이 있나요? Baidu 검색 결과를 미리 확인한 후 블로거는 Redis 트랜잭션 메커니즘을 사용하는 것이 권장되는 거의 모든 답변을 발견했습니다. 블로거는 redis 트랜잭션 메커니즘 사용을 권장하지 않습니다. 우리 프로덕션 환경은 기본적으로 Redis 클러스터 환경이므로 데이터 샤딩 작업이 수행됩니다. 단일 작업에 여러 키 작업이 포함되는 경우 이러한 키가 반드시 동일한 Redis 서버에 저장될 필요는 없습니다. 따라서 Redis의 트랜잭션 메커니즘은 매우 쓸모가 없습니다.

답변: 아래와 같습니다

(1) 이 열쇠를 조작하면 순서는 필요하지 않습니다

이 경우 분산형 자물쇠를 준비하면 모두가 자물쇠를 잡고, 잡은 후 그냥 설정 작업을 합니다. 자물쇠가 더 쉬워졌습니다.

(2) 이 키를 조작하려면 순서가 필요합니다

key1이 있다고 가정하면 시스템 A는 key1을 valueA로 설정해야 하고 시스템 B는 key1을 valueB로 설정해야 하며 시스템 C는 key1을 valueC로 설정해야 합니다.

예상 key1의 값에 따라 valueA-->valueB-->valueC의 순서로 변경됩니다. 이때 데이터베이스에 데이터를 쓸 때 타임스탬프를 저장해야 합니다. 타임스탬프는 다음과 같다고 가정합니다.

시스템 A 키 1 {값A 3:00}

시스템 B 키 1 {값B 3:05}

시스템 C 키 1 {값C 3:10}

시스템 B가 먼저 잠그면 key1의 값이 {valueB 3:05}로 설정됩니다. 시스템 A가 잠금을 획득할 때 저장된 valueA의 타임스탬프가 캐시에 저장된 타임스탬프보다 이전인 것을 발견하면 시스템 A는 설정 작업을 수행하지 않습니다. 등등.

큐를 사용하거나 설정 방법을 직렬 액세스로 전환하는 등 다른 방법도 사용할 수 있습니다. 한마디로 융통성을 가지세요.

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

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