>데이터 베이스 >Redis >Redis는 캐시 불일치 문제를 어떻게 해결합니까?

Redis는 캐시 불일치 문제를 어떻게 해결합니까?

WBOY
WBOY앞으로
2022-02-25 17:20:452555검색

이 기사에서는 Redis가 캐시 불일치 문제를 어떻게 해결하는지, 캐시와 데이터베이스 간의 데이터 불일치가 어떻게 발생하는지 함께 살펴보겠습니다. 모두에게 도움이 되기를 바랍니다.

Redis는 캐시 불일치 문제를 어떻게 해결합니까?

추천 학습: Redis 학습 튜토리얼

캐시와 데이터베이스 간의 데이터 불일치는 어떻게 발생합니까?

우선 "데이터 일관성"이 구체적으로 무엇을 의미하는지 이해해야 합니다. 실제로 여기서 "일관성"에는 두 가지 상황이 포함됩니다.

  • 캐시에 데이터가 있는 경우 캐시된 데이터 값은 데이터베이스의 값과 동일해야 합니다.
  • 캐시 자체에는 데이터가 없습니다. 그런 다음 데이터베이스의 값은 최신 값이어야 합니다.

이 두 가지 조건이 충족되지 않으면 캐시와 데이터베이스 간의 데이터 불일치 문제입니다. 그러나 캐시 읽기 및 쓰기 모드가 다른 경우 캐시 데이터 불일치 발생이 다르며 응답 방법도 달라집니다. 따라서 먼저 캐시 읽기 및 쓰기 모드에 따른 다양한 모드의 캐시 불일치를 이해합니다. 상태. 캐시를 읽기-쓰기 캐시와 읽기 전용 캐시로 나눌 수 있습니다.

읽기-쓰기 캐시의 경우 데이터를 추가, 삭제 또는 수정하려면 캐시에서 수행해야 합니다. 동시에 쓰기에 따라 데이터베이스에 동기적으로 다시 쓸지 여부를 결정해야 합니다. 백 전략을 채택했습니다.

동기식 직접 쓰기 전략: 캐시에 쓸 때 데이터베이스도 동기식으로 기록되고 캐시와 데이터베이스의 데이터가 일관됩니다.

비동기 쓰기 저장 전략: 캐시에 쓸 때 데이터베이스가 동기식으로 기록되지 않습니다. , 캐시 데이터베이스에서 데이터가 제거되면 다시 기록됩니다. 이 전략을 사용할 때 데이터가 데이터베이스에 다시 기록되지 않으면 캐시가 실패하며 이때 데이터베이스에는 최신 데이터가 없습니다.

따라서 읽기-쓰기 캐시의 경우 캐시의 데이터와 데이터베이스의 일관성을 보장하려면 동기식 직접 쓰기 전략을 채택해야 합니다. 그러나 이 전략을 채택할 경우 캐시와 데이터베이스를 동시에 업데이트해야 한다는 점에 유의해야 합니다. 따라서 비즈니스 애플리케이션에서 트랜잭션 메커니즘을 사용하여 캐시 및 데이터베이스 업데이트가 원자성으로 이루어지도록 해야 합니다. 즉, 함께 업데이트되거나 둘 다 업데이트되지 않고 오류 메시지가 반환되고 재시도가 수행되도록 해야 합니다. 그렇지 않으면 동기식 직접 쓰기를 달성할 수 없습니다.

물론 일부 시나리오에서는 데이터 일관성에 대한 요구 사항이 그다지 높지 않을 수 있습니다. 예를 들어 전자 상거래 제품의 중요하지 않은 속성이나 짧은 비디오의 생성 또는 수정 시간을 캐싱하는 경우 다음을 사용할 수 있습니다. 비동기 쓰기 전략.

읽기 전용 캐싱에 대해 이야기해 보겠습니다. 읽기 전용 캐시의 경우 새 데이터가 있으면 데이터베이스에 직접 기록되며, 데이터가 삭제되면 읽기 전용 캐시의 데이터를 유효하지 않은 것으로 표시해야 합니다. 이런 방식으로 애플리케이션이 추가, 삭제 또는 수정된 데이터에 이후에 액세스하면 캐시에 해당 데이터가 없기 때문에 캐시 누락이 발생합니다. 이때 애플리케이션은 데이터베이스의 데이터를 캐시로 읽어 들이므로 나중에 해당 데이터에 접근할 때 캐시에서 직접 읽을 수 있습니다.

다음으로 Tomcat을 예로 들어 MySQL에 데이터를 쓰고 삭제하는 방법을 설명하면 다음 그림과 같이 데이터 추가, 삭제, 수정 작업이 어떻게 수행되는지 설명할 수 있습니다.

그림에서 볼 수 있듯이 Tomcat 응용 프로그램은 데이터베이스에서 실행되는 데이터 X를 추가(삽입 작업), 수정(업데이트 작업), 삭제(삭제 작업)하는 경우 데이터베이스의 데이터가 직접 추가, 수정 및 삭제됩니다. 물론, 애플리케이션이 수정이나 삭제 작업을 수행하면 캐시된 데이터 X도 삭제됩니다.

그렇다면 이 과정에서 데이터 불일치가 발생할까요? 데이터를 추가하는 상황과 데이터를 삭제하는 상황이 다르다는 점을 고려하여 별도로 살펴보겠습니다.

  1. 새 데이터
    새 데이터인 경우 캐시에 대한 작업 없이 데이터가 데이터베이스에 직접 기록됩니다. 이때 캐시 자체에는 새 데이터가 없지만 데이터베이스에는 최신 값이 있습니다. 이 경우 방금 언급한 일관성의 두 번째 상황을 따르므로 이때 캐시에 있는 데이터와 데이터베이스의 데이터는 일관성이 있습니다.
  2. 데이터 삭제
    삭제 작업이 발생하면 애플리케이션은 데이터베이스를 업데이트하고 캐시의 데이터를 삭제해야 합니다. 이 두 작업이 원자성을 보장할 수 없는 경우, 즉 둘 다 완료되거나 둘 다 완료되지 않은 경우 데이터 불일치가 발생합니다. 이 문제는 더 복잡합니다. 분석해 보겠습니다.

애플리케이션이 캐시를 먼저 삭제한 다음 데이터베이스를 업데이트한다고 가정합니다. 캐시가 성공적으로 삭제되었지만 데이터베이스 업데이트에 실패하면 애플리케이션이 데이터에 다시 액세스할 때 캐시에 데이터가 없게 됩니다. 캐시 미스가 발생합니다. 그런 다음 애플리케이션이 다시 데이터베이스에 액세스하지만 데이터베이스의 값은 이전 값이고 애플리케이션은 이전 값에 액세스합니다.
예를 들어보겠습니다. 먼저 아래 사진을 보세요

Redis는 캐시 불일치 문제를 어떻게 해결합니까?

애플리케이션이 데이터 X의 값을 10에서 3으로 업데이트하려고 합니다. 먼저 Redis 캐시에서 X의 캐시 값을 삭제하지만 데이터베이스 업데이트에 실패합니다. 다른 동시 접근 요청이 있는 경우
먼저 데이터베이스를 업데이트한 다음 캐시의 값을 삭제하면 이 문제가 해결될 수 있는지 궁금하실 것입니다. 다시 분석해 보겠습니다.
애플리케이션이 데이터베이스 업데이트를 먼저 완료했지만 캐시 삭제 시 실패하는 경우 데이터베이스의 값은 새 값이고 캐시의 값은 이전 값이므로 확실히 일관성이 없습니다. 이때, 데이터에 접근하기 위한 다른 동시 요청이 있는 경우 일반적인 캐시 접근 프로세스에 따라 캐시를 먼저 쿼리하지만 이때는 이전 값을 읽습니다.
예를 들어 설명해 보겠습니다.

Redis는 캐시 불일치 문제를 어떻게 해결합니까?

애플리케이션은 데이터 X의 값을 10에서 3으로 업데이트하려고 합니다. 먼저 데이터베이스를 성공적으로 업데이트한 다음 3의 캐시를 삭제하고 Redis에 캐시된 X의 값은 10이며 이는 확실히 일관성이 없습니다. . 이때 다른 클라이언트가 X에 액세스하기 위한 요청을 보내면 먼저 Redis에서 쿼리하게 됩니다. 클라이언트는 캐시 적중을 찾지만 이전 값 10을 읽습니다.

좋아, 여기에서 데이터베이스를 업데이트하고 캐시된 값을 삭제하는 과정에서 두 작업이 먼저 실행되는 순서에 관계없이 하나의 작업이 실패하는 한 클라이언트가 Get을 읽게 된다는 것을 알 수 있습니다. 오래된 가치. 방금 언급한 두 가지 상황을 요약하기 위해 아래 표를 그렸습니다.

Redis는 캐시 불일치 문제를 어떻게 해결합니까?

문제의 원인을 알고 있는데 어떻게 해결해야 할까요?

데이터 불일치 문제를 해결하는 방법은 무엇입니까?

먼저 재시도 메커니즘이라는 방법을 소개하겠습니다.

구체적으로는 삭제할 캐시 값이나 업데이트할 데이터베이스 값을 메시지 큐에 임시 저장할 수 있습니다(예: Kafka 메시지 큐 사용). 애플리케이션이 캐시된 값을 삭제하거나 데이터베이스 값을 업데이트하는 데 실패하면 메시지 큐에서 값을 다시 읽고 다시 삭제하거나 업데이트할 수 있습니다.

성공적으로 삭제 또는 업데이트할 수 있으면 반복 작업을 피하기 위해 메시지 대기열에서 이러한 값을 제거합니다. 이때 데이터베이스와 캐시된 데이터의 일관성도 확인할 수 있습니다. 그렇지 않으면 다시 시도해야 합니다. 재시도가 특정 횟수를 초과했는데도 계속 실패하면 비즈니스 계층에 오류 메시지를 보내야 합니다.

아래 그림은 데이터베이스를 먼저 업데이트한 후 캐시 값을 삭제할 때, 캐시 삭제에 실패하고 재시도 후 삭제에 성공한 경우를 확인할 수 있는 모습입니다.

Redis는 캐시 불일치 문제를 어떻게 해결합니까?

방금 이야기한 것은 데이터베이스를 업데이트하고 캐시된 값을 삭제하는 과정에서 작업 중 하나가 실패하는 상황입니다. 실제로 이 두 작업이 처음 실행될 때 실패하지 않더라도, 동시 요청 수가 많으면 애플리케이션이 여전히 일관되지 않은 데이터를 읽을 수 있습니다.

마찬가지로 삭제 및 업데이트 순서에 따라 두 가지 상황으로 나눕니다. 두 경우 모두 우리의 솔루션도 다릅니다.

상황 1: 먼저 캐시를 삭제한 후 데이터베이스를 업데이트하세요.

스레드 A가 캐시 값을 삭제한 후 스레드 B가 데이터베이스를 업데이트할 시간이 생기기 전에 데이터 읽기를 시작한다고 가정합니다(예: 네트워크 지연이 있음). 이때 스레드 B는 캐시가 누락되어 데이터베이스에서만 읽을 수 있습니다. 이로 인해 두 가지 문제가 발생합니다.

  1. 스레드 B는 이전 값을 읽습니다.
  2. 스레드 B는 캐시가 없을 때 데이터베이스를 읽으므로 이전 값도 캐시에 기록하므로 다른 스레드가 이전 값을 읽게 됩니다. 캐시의 값.

스레드 B가 데이터베이스에서 데이터를 읽고 캐시를 업데이트한 후 스레드 A가 데이터베이스 업데이트를 시작합니다. 이때 캐시의 데이터는 이전 값이고 데이터베이스의 데이터는 최신 값입니다. 그리고 그 둘은 일관성이 없습니다.

이 상황을 요약하기 위해 표를 사용합니다.
Redis는 캐시 불일치 문제를 어떻게 해결합니까?

어떻게 해야 하나요? 해결책을 알려드리겠습니다.

스레드 A가 데이터베이스 값을 업데이트한 후 잠시 동안 대기 상태로 둔 다음 캐시 삭제 작업을 수행할 수 있습니다.

슬립 기간을 추가하는 이유는 스레드 B가 먼저 데이터베이스에서 데이터를 읽은 다음 누락된 데이터를 캐시에 쓴 다음 스레드 A가 이를 삭제할 수 있도록 하기 위함입니다. 따라서 스레드 A가 휴면 상태에 있는 시간은 스레드 B가 데이터를 읽고 캐시에 쓰는 시간보다 길어야 합니다. 이번에는 어떻게 결정하나요? 비즈니스 프로그램이 실행 중일 때 스레드가 데이터를 읽고 캐시를 쓰는 작업 시간을 계산하고 이를 기반으로 추정하는 것이 좋습니다.

이런 방식으로 다른 스레드가 데이터를 읽을 때 캐시가 누락되었음을 발견하므로 데이터베이스에서 최신 값을 읽습니다. 이 솔루션은 캐시된 값을 처음 삭제한 후 일정 기간 동안 삭제를 지연하므로 이를 "지연 이중 삭제"라고도 합니다.

다음 의사 코드는 "지연 이중 삭제" 솔루션의 예입니다. 살펴보실 수 있습니다.

redis.delKey(X)
db.update(X)
Thread.sleep(N)
redis.delKey(X)

시나리오 2: 데이터베이스 값을 먼저 업데이트한 다음 캐시 값을 삭제합니다.

스레드 A가 데이터베이스의 값을 삭제했지만 캐시 값을 삭제할 시간이 되기 전에 스레드 B는 데이터 읽기를 시작합니다. 이때 스레드 B는 캐시를 쿼리하여 캐시 적중을 발견합니다. 캐시에서 데이터를 직접 읽습니다. 그러나 이 경우 다른 스레드에서 캐시를 읽으려는 동시 요청이 많지 않으면 이전 값을 읽으려는 요청도 많지 않을 것입니다. 또한 스레드 A는 일반적으로 캐시된 값을 매우 빠르게 삭제하므로 다른 스레드가 다시 읽을 때 캐시 누락이 발생하고 데이터베이스에서 최신 값을 읽습니다. 따라서 이러한 상황은 비즈니스에 미치는 영향이 적습니다.

데이터베이스를 먼저 업데이트한 후 캐시된 값을 삭제하는 상황을 요약하기 위해 또 다른 표를 그려보겠습니다.
Redis는 캐시 불일치 문제를 어떻게 해결합니까?

자, 여기서 우리는 캐시와 데이터베이스 사이의 데이터 불일치가 일반적으로 두 가지 이유로 인해 발생한다는 것을 알게 되었으며 이에 상응하는 솔루션을 제공했습니다.

  • 캐시된 값을 삭제하거나 데이터베이스 업데이트에 실패하여 데이터 불일치가 발생하는 경우 재시도 메커니즘을 사용하여 삭제 또는 업데이트 작업이 성공했는지 확인할 수 있습니다.
  • 캐시된 값을 삭제하고 데이터베이스를 업데이트하는 두 단계에서 다른 스레드의 동시 읽기 작업이 발생하여 다른 스레드가 이전 값을 읽게 만드는 문제가 해결 방법은 이중 삭제를 지연시키는 것입니다.

추천 학습: Redis 비디오 튜토리얼

위 내용은 Redis는 캐시 불일치 문제를 어떻게 해결합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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