Как обеспечить согласованность кеша и базы данных в сценариях с высоким параллелизмом?

Java

анализ проблемы

В нашей повседневной разработке наиболее часто используемые сценарии кэширования показаны на рисунке ниже, что может быть только кэшированием данных для снижения нагрузки на базу данных и сокращения времени отклика интерфейса.

В этом решении не требуется учитывать высокий уровень параллелизма для записи в кеш и высокий уровень параллелизма для чтения и записи в кеш, проблем не будет, но если он находится в сценарии с высоким уровнем параллелизма, чтобы обеспечить согласованность между кешем и базе данных, необходимо решить как минимум следующую проблему:

Несогласованность данных при высокой параллельной записи

При чтении и записи с высокой степенью параллелизма порядок, в котором запрашивается выполнение каждого шага, не поддается контролю. Предположим, что есть запрос A и B, оба выполняющие процесс записи в это время.Запрос A должен изменить определенные данные на 1, а запрос B должен изменить определенные данные на 2. Если операция выглядит следующим образом, данные будут противоречивыми.проблема:

1. Запросите A выполнить операцию 1.1 по удалению кеша.

2. Запросите A выполнить операцию 1.2, чтобы обновить базу данных и изменить значение на 1.

3. Запросите B выполнить операцию 1.1 по удалению кеша.

4. B Выполняет операцию Запрошенную 1.2 Обновить базу данных, значение 2

5. Предположим, что сетевая задержка сервера, на котором находится запрос B, относительно мала, запрос B сначала обновляет кеш, а значение, соответствующее ключу в кеше, равно 2.

6. Запросите A обновить кеш, перезапишите данные, обновленные B в кеше, и измените значение, соответствующее ключу, на 1.

В это время данные в базе данных изменяются на B, значение равно 2, а данные в кеше равны 1, так что по истечении срока действия кеша пользователь считывает все грязные данные, несовместимые с базой данных.

Несогласованность данных при большом числе одновременных операций чтения и записи

При чтении и записи с высокой степенью параллелизма порядок, в котором запрашивается выполнение каждого шага, не поддается контролю. Предположим, что есть запрос A, выполняющий процесс записи в это время, исходное значение изменяется с 1 на 2, а B запрашивается выполнение процесса чтения.Если операция выглядит следующим образом, это вызовет проблему несогласованности данных :

1. Запрос на запись A выполняет операцию 1.1 по удалению ключа кэша, и значением является исходное значение 1.

2. Запрос чтения B выполняет операцию 2.1 и обнаруживает, что в кеше нет данных, затем выполняет операцию 2.2 для чтения базы данных и считывает старые данные, значение равно 1.

3. Написать запрос A на выполнение операции 1.2 по обновлению базы данных, изменив данные с 1 на 2.

4. Запрос на запись A выполняет операцию 1.3 для обновления кеша.В это время значение, соответствующее ключу данных в кеше, равно 2.

5. Запрос на чтение B выполняет операцию 2.3 для обновления кеша и устанавливает в кеш старые данные, прочитанные ранее 1. В это время значение, соответствующее ключу данных в кеше, равно 1.

Следовательно, если сетевая задержка сервера, на котором находится запрос на чтение B, относительно высока, а операция 2.3 выполняется позже, чем запрос на запись A, это приведет к тому, что запрос на запись A обновит кэш, а запрос на чтение B будет использовать старые данные, считанные ранее, для обновления кеша Данные в кеше несовместимы с данными в базе данных.

решение

Для обеспечения согласованности данных в Интернете существует множество решений, таких как:

1. Сначала удалите кэш, а затем обновите базу данных.

2. Сначала обновите базу данных, а затем удалите кеш.

3. Сначала удалите кеш, затем обновите базу данных, а затем выполните асинхронную задержку на некоторое время перед удалением кеша.

Однако в этих схемах есть различные проблемы.Место здесь ограничено, и даны только три относительно правильных схемы.Эти современные схемы также имеют свои ограничения.

Сценарий 1. Сериализация запроса на запись

написать запрос

1. Распределенная блокировка получена до обновления запроса на запись, а затем данные могут быть обновлены в базе данных.Если ее невозможно получить, она будет ждать.По истечении тайм-аута будет возвращена ошибка обновления.

2. После обновления обновите кеш.Если обновление не удалось, поместите его в очередь памяти для повторной попытки (повторите попытку с последними данными из базы данных для обновления кеша).

запрос на чтение

Когда запрос на чтение обнаруживает, что в кеше нет данных, он напрямую считывает базу данных и обновляет кеш после чтения.

Суммировать

Это техническое решение обеспечивает согласованность данных за счет реализации сериализации запросов на запись, но приводит к снижению пропускной способности. Это больше подходит для бизнеса, связанного с банковским делом, потому что для банковских проектов обеспечение согласованности данных важнее, чем доступность.Это все равно, что подойти к депозитной машине, чтобы положить деньги.При снятии денег, чтобы обеспечить безопасность счета, пользователи будут запрос на выполнение операции Ожидание ответа некоторое время, в течение которого банкомат фактически недоступен.

Вариант 2. Сначала обновите базу данных, асинхронно удалите кеш и повторите попытку после сбоя удаления.

1. Сначала обновите базу данных

2. Асинхронно удалить кеш (если БД разделена на чтение и запись, нужно задержать удаление при удалении кеша, иначе может быть так, что при удалении кеша ведомая библиотека не получила обновленные данные, и др. запросы на чтение отправляются в подчиненную библиотеку для чтения, а затем старые данные помещаются в кеш.)

3. В случае сбоя удаления кеша поместите удаленный ключ в очередь памяти или очередь сообщений для асинхронной повторной попытки.

дивергентное мышление

После обновления базы данных, почему бы нам просто не обновить ее напрямую, а вместо этого удалить кеш?

Это связано с тем, что если кеш обновляется напрямую, в сценарии с высоким параллелизмом, когда есть несколько запросов на обновление, трудно гарантировать, что запрос на обновление базы данных обновит кеш позже, то есть проблема с высокой параллельной записью выше . Если используется кеш удаления, база данных может быть прочитана при следующем чтении, а кеш может быть обновлен для обеспечения согласованности.

Сценарий 3. Бизнес-проекты обновляют базу данных, а другие проекты подписываются на обновления бинлога

1. Бизнес-элементы напрямую обновляют базу данных.

2. Проект cannal прочитает бинлог базы данных, а затем пропарсит и отправит сообщение в kafka.

3. Затем элемент обновления кеша подписывается на тему.Получив сообщение об обновлении операции базы данных от kafka, обновить кеш.При сбое обновления кеша создать новый асинхронный поток для повторной попытки или отправить операцию в очередь сообщений, а затем обработать его позже.

Суммировать:

Однако в этой схеме после обновления базы данных в кеше остается старое значение, и кеш необходимо обновить после того, как элемент обновления кеша использует сообщение, а в кеше остается самое последнее значение. Поэтому будет определенная задержка между завершением операции обновления и вступлением обновления в силу.

Наконец

Если у вас есть другие технические решения, пожалуйста, присоединяйтесь к группе для обсуждения!

Друг в комментарии спросил, что такое стратегия отложенного двойного удаления?

Вот объяснение: стратегия отложенного двойного удаления заключается в том, чтобы сначала удалить кеш, затем обновить базу данных, а затем удалить кеш через короткий промежуток времени асинхронно (время зависит от времени синхронизации master-slave MySQL).

Это связано с тем, что когда MySQL отделен от чтения и записи (запросы на запись записываются в основную библиотеку, а запросы на чтение считываются из подчиненной библиотеки), после того, как мы обновим основную библиотеку, потребуется некоторое время, чтобы подчиненная библиотека получила обновления.

Если это запрос на запись для обновления основной базы данных, кеш сразу же удаляется во второй раз, а подчиненная база данных MySQL не получила обновление или старые данные, то запрос на чтение напрямую считывает старые данные из базы данных. , а набор данных в кеш — это старые данные, просто данные будут несогласованными, поэтому это также является первоначальным намерением стратегии отложенного двойного удаления.

Ссылка на ссылку:

woooooo.cn blogon.com/-texture/afraid/11…

блог woo woo woo.cn на.com/now being/afraid/9…

Обзор содержания сухих грузов:

[Интервью с Дачангом, выпуск 01] Как обеспечить согласованность кэша и базы данных в сценариях с высокой степенью параллелизма?

[Интервью с Дачангом, выпуск 02] Как очистить ключи Redis с истекшим сроком действия?

[Интервью с Дачангом 03] Как MySQL решает проблему фантомного чтения?

[Интервью с Дачангом 04] Расскажите о том, как выполняется оператор обновления MySQL?

[Интервью с Дачангом, выпуск 05] Расскажите, как вы понимаете блокировку в MySQL?

[Интервью с Дачангом 06] Расскажите о своем понимании сохраняемости Redis?

[Интервью с Дачангом, выпуск 07] Расскажите, как вы понимаете синхронизированные блокировки?

[Интервью с Дачангом 08] Расскажите о своем понимании HashMap?