MySQL 데이터를 Redis 캐시에 동기화하는 몇 가지 방법

1 Mysql은 데이터를 확인한 다음 동기식으로 Redis에 씁니다.

  1. 단점 1: redis 자체에 동기식 쓰기가 지연되어 재시도가 필요하기 때문에 인터페이스에 지연이 발생하며, redis 쓰기에 실패할 경우 재시도가 필요하므로 시간이 더 소요됩니다.

  1. 단점 2: 디커플링 없음, redis가 충돌하면 스레드가 바로 중단됨

  1. 단점 3: 데이터베이스를 인위적으로 생성한 경우 해당 Redis를 인위적으로 삭제하지 않으면 동기화가 되지 않으나 Redis를 삭제하는 과정에서도 시간차가 있음

2 Mysql이 데이터를 확인한 후 MQ를 보내 소비자 스레드에서 Redis를 동기화합니다.

  1. 단점 1: MQ 레이어가 더 많습니다. 즉, 동기화 지연 문제가 발생할 가능성이 높습니다.

  1. 단점 2: MQ의 가용성을 방지하기 위해

  1. 단점 3: 데이터베이스가 사람이 만든 것이라면 동기화가 불가능하다

  1. 장점 1: 인터페이스 반환 지연 문제를 크게 줄일 수 있습니다.

  1. 장점 2: MQ 자체에 재시도 메커니즘이 있으므로 수동으로 재시도 코드를 작성할 필요가 없습니다.

  1. 장점 3: 디커플링, 서로 간섭하지 않고 쿼리 Mysql과 동기식 Redis를 완전히 분리

3 Mysql의 Binlog 파일 구독(Canal의 도움으로 수행 가능)

  1. CanalServer는 MysqlServer 메인 라이브러리의 Binlog 파일을 구독하기 위해 MysqlServer 슬레이브 라이브러리인 척합니다.

  1. Canal이 시작되면 해당 메시지 MQ(RabbitMQ, RocketMQ, Kafka)를 구성하고 Binlog 파일에서 변경을 감지하면 변경된 sql 문을 json 형식으로 변환하여 메시지 내용으로 MQ에 보냅니다.

  1. 프로젝트에서 해당 MQ를 모니터링하는 한 Binlog 변경 내용을 가져올 수 있으며 Json 데이터에는 명확한 작업 유형(CURD)과 해당 데이터가 있습니다. 해당 데이터를 redis에 동기화

  1. 단점 1: Canal이 Binlog를 구독하는 전체 작업 과정이 단일 스레드이므로 초고 동시성의 경우 성능이 좋지 않을 수 있습니다. 물론 다수의 canal과 다수의 consumer가 배치될 수 있지만 메시지의 반복 소비 문제에 주의를 기울여야 하며 멱등성 검사가 이루어져야 합니다.

  1. 장점 1: 데이터베이스를 인위적으로 변경해도 모니터링 및 동기화

  1. 장점 2: 비동기식 및 동기식, 인터페이스 반환을 위한 추가 지연 없음

4 지연 이중 삭제

  1. 수정된 SQL을 실행하기 전에 redis 데이터를 먼저 삭제하십시오.

  1. 업데이트 SQL 실행

  1. 잠시 지연

  1. redis 데이터를 다시 삭제

// 延迟双删伪代码
deleteRedisCache(key);   // 删除redis缓存
updateMysqlSql(obj);        // 更新mysql
Thread.sleep(100);           // 延迟一段时间
deleteRedisCache(key);   // 再次删除该key的缓存

단점: 지연 시간을 제어하기 쉽지 않고 지연이 얼마나 오래 지속되는지 평가하기 어렵습니다.

확장: 지연 이중 삭제를 사용하지 않는 경우 캐시를 삭제한 다음 mysql 데이터를 변경하십시오. 이 두 단계만의 문제는 무엇입니까?

5. 단일 요청, 단일 스레드는 문제가 없지만 높은 동시성 및 다중 스레드에서는 문제가 발생합니다.

6. Thread1 스레드가 데이터를 업데이트하려는 경우 Thread1 스레드는 redis를 정리합니다.

7. 이때 Thread2 쓰레드가 오는데 쓰레드1이 mysql 업데이트를 완료하지 않은 상태

8. Thread2 쿼리 redis는 null이어야 합니다. 이때 Thread2는 mysql을 확인한 다음 찾은 데이터를 캐시에 씁니다.

9. Thread1은 mysql 데이터를 수정할 시간이 없었기 때문에 이때 Thread2가 감지한 데이터는 [오래된 데이터]이고 Thread2는 이전 데이터를 Redis에 다시 씁니다.

10. 이때 Thread3 스레드가 와서 Redis에 쿼리하여 데이터가 있는지 확인한 다음 캐시된 데이터를 직접 가져옵니다. 이때 [Thread3가 이전 데이터를 찾습니다], 이전 데이터를 직접 반환합니다. 이것이 문제입니다.

11. 지연 이중 삭제의 두 번째 삭제 기능은 Thread2가 이전 데이터를 다시 쓰는 것을 방지하는 것입니다. 지연 이중 삭제를 사용하면 Redis를 쿼리할 때 Thread3는 여전히 null을 가져오고 mysql에서 최신 데이터를 가져옵니다.

12. 따라서 정상적인 지연 시간은 Thread2가 캐시를 확인하고 mysql 데이터를 가져와서 redis에 저장하기까지의 전체 시간이 Thread1의 지연 시간과 같아야 하지만 Thread2의 처리 시간은 많은 요인에 의해 영향을 받습니다. 그래서 그것이 얼마나 오래 될지 결정하기가 어렵습니다.

5 지연 이중 쓰기

// 延迟双写伪代码
updateMysqlSql(obj);        // 更新mysql
addRedis(key);   // 再次删除该key的缓存

앞서 언급한 코드 결함;

  1. 높은 동시성에서 두 개의 스레드가 동시에 위의 코드를 실행하고 mysql을 수정하며 수정된 내용이 부당하여 Redis와 Mysql 간의 데이터 불일치가 발생할 수 있습니다.

  1. T1 쓰레드가 updateMysqlSql을 실행한 후 row lock이 해제되는데, 이때 T2 쓰레드는 updateMysqlSql과 addRedis를 실행하고, 마지막으로 T1은 addRedis를 실행하게 되는데 이런 상황에서 데이터베이스는 T2 쓰레드의 데이터로 변경되지만 Redis는 T1 스레드의 데이터입니다.

优化
// 完美延迟双写伪代码
开启事务
updateMysqlSql(obj);        // 更新mysql
addRedis(key);   // 再次删除该key的缓存
提交事务

위 코드 수정:

  1. 두 줄의 코드를 하나의 트랜잭션에 넣으면 T1이 Mysql과 Redis의 실행을 완료해야만 T2가 실행을 시작할 수 있어 데이터 일관성을 보장할 수 있습니다. 분산 잠금을 사용하는 것이 좋습니다.

  1. 이중 작성의 단점: Mysql과 Redis는 단일 스레드입니다. 성능면에서 좋지 않으므로 사용하지 않는 것이 좋습니다.

6 요약

비동기 동기화에는 Canal 방법을 사용하는 것이 좋습니다. MQ 방법 다음에

Supongo que te gusta

Origin blog.csdn.net/qq_37284798/article/details/129518953
Recomendado
Clasificación