Разговор о базах данных, когерентности кеша

Java

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

научно-популярный

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

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

Кэширование — одно из самых важных, эффективных и простых средств повышения производительности программы.

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

image.png

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

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

Эта схема явно порочна.

Две параллельные операции чтения и записи:

  1. Сначала выполняется операция записи, и кеш удаляется;
  2. Когда операция записи не обновила базу данных, снова приходит запрос на чтение, и обнаруживается, что кеш не попал, поэтому он обращается к базе данных для извлечения старых данных;
  3. Операция записи обновляет базу данных;
  4. Операции чтения помещают старые данные в кеш.

Таким образом, данные в базе данных и данные в кеше несовместимы.Чтобы лучше понять этот процесс, вот некрасивая картина:

image.png

Этот план явно не сработает, но действительно ли он бесполезен?

Нет, представим себе такой сценарий: приходит запрос на запись и удаляет кеш, в это время на сервере Redis внезапно возникают проблемы, или в сети внезапно возникают проблемы, в результате чего удаление кеша не выполняется, выбрасывая исключение , в результате чего программа Операция по изменению базы данных не была продолжена. С точки зрения согласованности базы данных и кеша согласованность базы данных и кеша гарантирована.Данные, сохраняемые ими, одинаковы, хотя старые данные сохраняются.

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

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

Увидев проблемы с первым решением, все, должно быть, подумали, что и у этого решения такая же проблема.

Без кэширования две параллельные операции чтения и записи:

  1. Сначала пришла операция чтения, обнаружила, что кеша нет, и пошла читать данные в БД, на этот раз она почему-то застряла, и данные не были вовремя помещены в кеш;
  2. Приходит операция записи, модифицируется база данных и удаляется кеш;
  3. Операция чтения возобновляется, и старые данные записываются в кэш.

image.png

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

Сказав так много, я не видел фатальной проблемы сначала изменить базу данных, а затем удалить кеш.Не волнуйтесь, давайте продолжим представлять этот сценарий: приходит операция записи и изменяет базу данных, но когда кеш удаляется из-за Redis Проблема с сервером или проблема с сетью, которая приводит к сбою удаления кеша Таким образом, база данных сохраняет новые данные, но данные в кеше все еще старые данные.Правильная база данных и кеш несовместимы.

отложенное двойное удаление

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

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

图片.png

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

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

очередь памяти

Вышеупомянутые три метода имеют определенные проблемы:

  • Две операции изменения базы данных и удаления кэша связаны друг с другом, и нет единой ответственности;
  • Если операции записи выполняются часто, это может вызвать определенную нагрузку на Redis;
  • Что делать, если не удается удалить кеш?

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

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

Но есть минусы в этом:

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

Но нет способа сделать это, и нет идеального решения.

сторонняя очередь

Вообще говоря, система делится на систему переднего плана и фоновую систему.Система переднего плана в основном предназначена для операций чтения, а фоновая система имеет операции записи.

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

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

Серверная система Сяо Мин: Какой формат является ключевым форматом кэша сведений о продукте в вашей внешней системе? Отправьте меня. Система стойки регистрации Xiaohua: Продукт: XXXXX. Фоновая система Сяо Мин: Хорошо.

Через несколько дней Сяохуа нашел Сяомина.

Система стойки регистрации Сяохуа: Нет. Почему вы не удалили кеш сведений о товаре в событии? Фоновая система Сяо Мин: Нани, откуда мне знать, что у вас есть два кеша, пришлите мне формат ключа кеша сведений о продукте в случае. Система стойки регистрации Xiaohua: Деятельность: Продукт: XXXX. Фоновая система Сяо Мин: Хорошо.

Несколько дней спустя разработка системы заказов снова нашла Сяо Мина. Система заказа Xiaoqiang: после изменения сведений о продукте вы также должны кэшировать и удалить сведения о продукте в заказе. Фоновая система Сяо Мин: . . .

Через несколько дней разработчик рекламной системы снова нашел Сяо Мина. Рекламная система Xiao Wang: После того, как вы изменили информацию о продукте, вы также должны удалить кэш информации о продукте в рекламе.

Закулисная система Сяо Мин умерла в возрасте 25 лет.

Если ссылаться на стороннюю очередь, такую ​​как RabbitMQ, Kafka, Сяомин не "умрет". После того, как Сяомин фоновой системы модифицирует базу данных, ему не нужно заботиться о кеше. Ему нужно только кинуть данные ID в очередь сообщений.Развитие и потребление рекламной системы и системы заказов удаляют кеш данных в очереди сообщений.

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

На этом сегодняшняя тема заканчивается.