>  기사  >  데이터 베이스  >  Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법

Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법

WBOY
WBOY앞으로
2022-03-17 18:50:153148검색

이 글은 Redis에 대한 관련 지식을 제공합니다. 캐시 업데이트, 데이터베이스 업데이트 등을 포함하여 Redis 캐시와 데이터베이스의 일관성을 보장하는 방법과 관련된 문제를 주로 소개합니다. 모든 분들께 도움이 되기를 바랍니다. .

Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법

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

1. 4가지 동기화 전략:

캐시와 데이터베이스 간의 이중 쓰기 일관성을 보장하기 위해 총 4가지 방법, 즉 4가지 동기화 전략이 있습니다.

먼저 캐시를 업데이트한 다음 데이터베이스를 업데이트하세요.
  1. 먼저 캐시를 삭제한 다음 데이터베이스를 업데이트하세요.
  2. 먼저 데이터베이스를 업데이트한 다음 캐시를 삭제하세요.
  3. 이 4가지 동기화 전략 중에서 비교해야 할 것은 다음과 같습니다.
  4. 캐시를 업데이트하거나 캐시를 삭제하는 데 어떤 방법이 더 적합합니까? 데이터베이스를 먼저 운영해야 할까요, 아니면 캐시를 먼저 운영해야 할까요?

2. 캐시 업데이트 또는 캐시 삭제

다음으로 캐시를 업데이트해야 할지 아니면 캐시를 삭제해야 할지 분석해 보겠습니다.

2.1 캐시 업데이트

장점

:

캐시는 데이터가 변경될 때마다 적시에 업데이트되므로 쿼리 중에 누락이 발생할 가능성이 적습니다.

단점:

캐시 업데이트 비용이 상대적으로 비쌉니다. 데이터를 캐시에 기록하기 전에 복잡한 계산을 거쳐야 하는 경우 캐시를 자주 업데이트하면 서버 성능에 영향을 미칩니다. 데이터가 자주 작성되는 비즈니스 시나리오의 경우 캐시가 자주 업데이트되면 데이터를 읽는 비즈니스가 없을 수 있습니다.

2.2 캐시 삭제

장점

:

간단한 조작, 업데이트 조작이 복잡한지 여부에 관계없이 캐시에 있는 데이터가 직접 삭제됩니다.

단점:

캐시를 삭제한 후 다음 쿼리 캐시가 누락되어 데이터베이스를 다시 읽어야 합니다. 위의 비교에서 일반적으로 캐시를 삭제하는 것이 더 나은 해결책입니다.

3. 데이터베이스를 먼저 운영해야 할지, 캐시를 먼저 운영해야 할지 분석해 보겠습니다. 먼저 캐시를 먼저 삭제하고 데이터베이스를 먼저 업데이트한 후 실패할 때 비교해 보겠습니다.

3.1 캐시를 먼저 삭제한 다음 데이터베이스를 업데이트합니다

그림 설명을 추가해주세요

위와 같이 캐시가 먼저 삭제된 후 데이터베이스가 삭제됩니다. 업데이트 실패 시 발생할 수 있는 문제 :

    出现失败时进行一个对比:

    3.1 先删除缓存再更新数据库

    Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법
    如上图,是先删除缓存再更新数据库,在出现失败时可能出现的问题:

    • 线程A删除缓存成功,线程A更新数据库失败;
    • 线程B从缓存中读取数据;由于缓存被删,进程B无法从缓存中得到数据,进而从数据库读取数据;此时数据库中的数据更新失败,线程B从数据库成功获取旧的数据,然后将数据更新到了缓存。
    • 最终,缓存和数据库的数据是一致的,但仍然是旧的数据

    3.2 先更新数据库再删除缓存

    Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법
    如上图,是先更新数据库再删除缓存,在出现失败时可能出现的问题:

    • 线程A更新数据库成功,线程A删除缓存失败;
    • 线程B读取缓存成功,由于缓存删除失败,所以线程B读取到的是缓存中旧的数据。
    • 最后线程A删除缓存成功,有别的线程访问缓存同样的数据,与数据库中的数据是一样。
    • 最终,缓存和数据库的数据是一致的,但是会有一些线程读到旧的数据。

    经过上面的比较,我们发现在出现失败的时候,是无法明确分辨出先删缓存和先更新数据库哪个方式更好,以为它们都存在问题。后面我们会进一步对这两种方式进行比较,但是在这里我们先探讨一下,上述场景出现的问题,应该如何解决呢?

    实际上,无论上面我们采用哪种方式去同步缓存与数据库,在第二步出现失败的时候,都建议采用重试机制解决,上面两幅图中已经画了。




    下面我们再将先删缓存与先更新数据库,在没有出现失败时进行对比:
    Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법
    如上图,是先删除缓存再更新数据库,在没有出现失败时스레드 A는 캐시를 성공적으로 삭제했지만 스레드 A는 데이터베이스 업데이트에 실패했습니다.

    🎜스레드 B는 캐시가 삭제되었기 때문에 캐시에서 데이터를 읽습니다. B는 캐시에서 데이터를 가져올 수 없지만 데이터베이스에서 데이터를 읽습니다. 이때 데이터베이스의 데이터 업데이트가 실패했습니다. 스레드 B는 데이터베이스에서 이전 데이터를 성공적으로 가져온 다음 데이터를 캐시에 업데이트했습니다. 🎜🎜🎜결국 캐시와 데이터베이스 데이터는 일치하지만 여전히 오래된 데이터입니다🎜🎜
🎜3.2 데이터베이스를 먼저 업데이트한 후 캐시를 삭제하세요🎜🎜그림 설명을 추가해주세요🎜 위와 같이 데이터베이스가 먼저 업데이트된 후 캐시가 삭제됩니다. 실패 가능한 문제: 🎜
    🎜스레드 A가 데이터베이스를 성공적으로 업데이트했지만 스레드 A가 캐시를 삭제하지 못했습니다. 🎜🎜스레드 B가 캐시를 성공적으로 읽었지만 캐시 삭제에 실패했기 때문에 스레드 B가 실패했습니다. 캐시의 이전 데이터를 읽습니다. 🎜🎜마지막으로 스레드 A는 캐시를 성공적으로 삭제하고 다른 스레드는 데이터베이스의 데이터와 동일한 캐시의 동일한 데이터에 액세스합니다. 🎜🎜🎜결국 캐시와 데이터베이스 데이터는 일치하지만 일부 스레드는 이전 데이터를 읽습니다. 🎜🎜
🎜위의 비교 결과 실패 시 캐시를 먼저 삭제하거나 데이터베이스를 먼저 업데이트하는 것 중 어떤 방법이 더 나은지 명확하게 구분할 수 없다는 것을 발견했습니다. 그들에게는 문제가 있습니다. 나중에 이 두 가지 방법을 더 자세히 비교할 것이지만 여기서는 먼저 위의 시나리오에서 발생하는 문제를 해결하는 방법에 대해 논의하겠습니다. 🎜🎜실제로 캐시와 데이터베이스를 동기화하기 위해 어떤 방법을 사용하든 두 번째 단계가 실패하면 위의 두 그림에 그려진 재시도 메커니즘을 사용하는 것이 좋습니다. . 🎜


🎜이제 캐시를 먼저 삭제하고 데이터베이스를 먼저 업데이트하는 것과 실패가 없는 경우를 비교해 보겠습니다. 🎜그림 설명을 추가해주세요🎜 위와 같이 캐시를 먼저 삭제한 후 데이터베이스를 삭제합니다. 업데이트되었습니다. 가 없습니다. 실패 시 발생할 수 있는 문제: 🎜<ul> <li>스레드 A가 캐시를 성공적으로 삭제했습니다. </li> <li>스레드 B가 성공적으로 데이터베이스를 읽고 이전 데이터를 가져왔습니다. </li> <li>스레드 A를 성공적으로 업데이트했습니다. 새 데이터가 데이터베이스에 성공적으로 업데이트됩니다. </li> <li>프로세스 A의 두 단계가 성공한 것을 볼 수 있지만 동시성으로 인해 프로세스 B가 두 단계 사이에 캐시에 액세스했습니다. <li>최종 결과는 오래된 데이터가 캐시에 저장되고 새 데이터가 데이터베이스에 저장되며 두 데이터가 일치하지 않는다는 것입니다. </li> </ul> <p><strong></strong></p> <hr> 위 그림과 같이 데이터베이스가 먼저 업데이트된 다음 캐시가 삭제됩니다. <hr>에서 가능한 문제: <p><img src="https://img.php.cn/upload/article/000/000/067/e73f1a06231a665bb67debaa27b6baf0-3.png" alt="Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법"><br>스레드 A가 데이터베이스를 성공적으로 업데이트했습니다. <code>没有出现失败时

스레드 A가 캐시를 성공적으로 삭제했습니다.
  • 최종 캐시는 데이터베이스의 데이터와 일치하며 둘 다 최신 데이터
  • 임을 알 수 있습니다. 그러나 스레드 B는 이 프로세스 중에 이전 데이터를 읽습니다. 이 두 단계 사이에 캐시의 이전 데이터를 읽는 스레드 B와 같은 다른 스레드가 있을 수 있지만 이 두 단계의 실행 속도가 더 빠르므로 영향은 없습니다. 큰. 이 두 단계 이후에는 다른 프로세스가 캐시된 데이터를 읽을 때 프로세스 B와 유사한 문제가 발생하지 않습니다.
  • 최종 결론:

비교해 보면 데이터베이스를 먼저 업데이트한 다음 캐시를 삭제하는 것이 영향이 덜한 솔루션이라는 것을 알 수 있습니다. 두 번째 단계가 실패하면 재시도 메커니즘을 사용하여 문제를 해결할 수 있습니다. 4. 지연된 이중 삭제

위에서 언급했듯이

캐시를 먼저 삭제한 다음 데이터베이스를 업데이트하면

, 장애가 없더라도 데이터 불일치

가 발생할 수 있습니다. 실제 응용 프로그램에서 특정 고려 사항으로 인해 이 방법을 선택해야 한다면 이 문제를 해결할 수 있는 방법이 있습니까? 대답은 '예'입니다. 즉, 지연된 이중 삭제 전략을 채택하는 것입니다

:

캐시를 삭제하고 N밀리초 동안 잠자기; 캐시를 다시 삭제하세요.

    	public void write(String key, Object data) {
            Redis.delKey(key);
            db.updateData(data);
            Thread.sleep(1000);
            Redis.delKey(key);
        }
  1. 일정 기간 동안 차단한 후 캐시를 다시 삭제하면 이 과정에서 캐시에 있는 일치하지 않는 데이터가 삭제됩니다
  2. . 구체적인 시간은 대략적인 업무 시간을 평가하고 이에 맞춰 설정해야 합니다.
  3. 4.1 아키텍처가 읽기와 쓰기를 분리한다면 어떻게 해야 할까요?
  4. 데이터베이스가 읽기-쓰기 분리 아키텍처를 채택하면 아래와 같이 새로운 문제가 발생합니다.

이때 요청 A(업데이트 작업)와 요청 B(쿼리 작업)라는 두 가지 요청이 왔습니다.

A에게 업데이트 작업을 수행하고 Redis를 삭제하도록 요청합니다.

메인 라이브러리에 업데이트 작업을 수행하고, 메인 라이브러리와 슬레이브 라이브러리에 데이터를 동기화하도록 요청합니다.


B에게 쿼리 작업을 수행하고 데이터가 없음을 확인합니다. Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법
슬레이브 라이브러리로 이동하여 데이터를 가져옵니다.

    현재 데이터 동기화가 완료되지 않았으며 얻은 데이터는 이전 데이터입니다.
  1. 이때 해결 방법은 데이터베이스에 쿼리하는 것입니다. Redis에 데이터를 채운 다음 쿼리를 위해 기본 라이브러리를 가리키도록 강제합니다.
  2. 삭제에 실패하면 어떻게 해야 하나요?
  3. 그래도 삭제에 실패할 경우 재시도 횟수를 늘릴 수 있으나 이 횟수는 제한되어야 합니다. 특정 횟수를 초과하는 경우 오류 보고, 로그 기록, 이메일 알림 전송 등의 조치를 취해야 합니다.
5. 메시지 대기열을 사용하여 삭제 보상

데이터베이스를 먼저 업데이트한 다음 캐시를 삭제하세요이런 상황도 문제가 발생할 수 있습니다. 예를 들어 데이터베이스가 성공적으로 업데이트되었지만 캐시 삭제 단계에서 오류가 발생하고 그러면 삭제가 실패합니다. 이때 캐시를 다시 읽을 때마다 데이터가 잘못됩니다.

이때 해결 방법은 메시지 대기열을 사용하여 삭제를 보상하는 것입니다. 구체적인 비즈니스 로직은 다음과 같습니다.

스레드 A에게 먼저 데이터베이스 업데이트를 요청합니다. Redis 삭제 시 오류가 보고되어 삭제에 실패했습니다.
Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법이때 Redis의 키가 사용됩니다. 메시지 본문으로 메시지 큐로 보내기

시스템이 메시지 큐에서 보낸 메시지를 받은 후 Redis를 다시 삭제합니다.

  1. 그러나 이 솔루션에는 많은 문제가 발생한다는 단점이 있습니다. 비즈니스 코드에 대한 침입과 심층 결합이 동시에 최적화 방법이 있을 것입니다. 우리는 Mysql 데이터베이스를 업데이트한 후 binlog 로그에서 해당 작업을 찾을 수 있다는 것을 알고 있습니다. 그런 다음 binlog를 구독할 수 있습니다. 캐시를 운영하기 위한 Mysql 데이터베이스의 로그입니다.
  2. 추천 학습:
  3. Redis 튜토리얼

위 내용은 Redis 캐시와 데이터베이스 간의 일관성을 보장하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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