Как обеспечить согласованность данных, когда кеш и база данных записываются дважды?
При оптимизации системы мне пришла в голову идея многоуровневого хранения данных. Поскольку в системе будут некоторые данные, требования к некоторым данным в реальном времени невелики, например, к некоторой информации о конфигурации. По сути, конфигурация будет меняться только один раз через долгое время. Однако к некоторым данным предъявляются очень высокие требования в реальном времени, например данные о заказах и потоках. Таким образом, данные разделены на три уровня в соответствии с требованиями к данным в реальном времени.
Уровень 1: данные заказа и данные о потоке платежей; к этим двум частям данных предъявляются высокие требования к точности и реальному времени, поэтому без добавления какого-либо кэша операции чтения и записи будут напрямую управлять базой данных.
Уровень 2: данные, связанные с пользователями; эти данные связаны с пользователями и имеют характеристики больше читать и меньше писать, поэтому мы используем Redis для кэширования.
Уровень 3: информация о конфигурации платежа; эти данные не имеют ничего общего с пользователями и имеют характеристики небольшого объема данных, частого чтения и почти отсутствия изменений, поэтому мы используем локальную память для кэширования.
Однако до тех пор, пока используется кеш, будь то локальная память для кеша или redis для кеша, будет проблема синхронизации данных, потому что информация о конфигурации кэшируется в памяти, и память не может воспринимать изменение данных в базе данных. Это приведет к тому, что данные в базе данных будут несовместимы с данными в кэше. Далее мы обсудим обеспечение согласованности данных, когда кеш и база данных записываются дважды.
решение
Итак, здесь мы перечисляем все стратегии и обсуждаем их плюсы и минусы.
- Сначала обновите базу данных, затем обновите кеш.
- Сначала обновите базу данных, затем удалите кеш.
- Сначала обновите кэш, затем обновите базу данных.
- Сначала удалите кэш, затем обновите базу данных.
Сначала обновите базу данных, затем обновите кеш.
Этот сценарий вообще никем не используется, основная причина это шаг обновления кеша, почему? Поскольку некоторые бизнес-требования существуют в значении кэша, которое не проверяется напрямую из базы данных, а некоторые требуют серии вычислений для вычисления значения кэша, обновление кэша после этого времени на самом деле очень дорого. Если запросов на запись данных в БД в это время большое количество, а запросов на чтение не так много, то при обновлении кеша на каждый запрос на запись в это время потеря производительности очень велика.
Например, в базе данных есть значение 1. В это время у нас есть 10 запросов на добавление к нему 1 каждый раз, но в этот период не происходит ни одной операции чтения. Если мы сначала используем метод обновления базы данных, то В этот момент будет десять запросов на обновление кеша, и будет сгенерировано большое количество холодных данных.Если мы удалим кеш вместо обновления кеша, то кеш будет обновляться только один раз, когда придет запрос на чтение .
Сначала обновите кэш, затем обновите базу данных.
Этот случай не должен нуждаться в нашем рассмотрении, он такой же, как и первый случай.
Сначала удалите кэш, затем обновите базу данных.
У программы также будут проблемы, и конкретные причины следующие.
На данный момент есть два запроса: запрос A (операция обновления) и запрос B (операция запроса).
- Запрос A сначала удалит данные в Redis, а затем перейдет к базе данных для операции обновления.
- В это время, когда запрос B увидит пространство данных и время в Redis, он запросит значение в базе данных и запишет его в Redis.
- Но в это время запрос A не был успешно обновлен или транзакция не была зафиксирована.
Тогда возникнет проблема несоответствия между базой данных и данными Redis. Как это решить? На самом деле, самое простое решение — отложить стратегию двойного удаления.
Однако есть еще одна проблема с удалением кеша после совершения вышеупомянутой гарантийной транзакции: если вы используете архитектуру разделения чтения и записи Mysql, на самом деле будет разница во времени между синхронизацией master-slave.
На данный момент есть два запроса: запрос A (операция обновления) и запрос B (операция запроса).
- Запросить операцию обновления, удалить Redis
- Основная библиотека запрашивается для выполнения операции обновления, а основная библиотека и ведомая библиотека выполняют операции синхронизации данных.
- Попросите B запросить операцию и обнаружить, что в Redis нет данных.
- получить данные из репозитория
- В настоящее время данные синхронизации не завершены, полученные данные являются старыми данными.
В настоящее время решение состоит в том, чтобы заставить Redis указывать на основную базу данных для запроса операций базы данных для заполнения данных.
Сначала обновите базу данных, затем удалите кеш.
Проблема: В этой ситуации тоже будут проблемы.Например база обновляется успешно,но на этапе удаления кеша возникает ошибка,и удаление не проходит.Тогда каждый раз при повторном чтении кеша данные каждый раз неверны.
Решение на данном этапе состоит в том, чтобы использовать очереди сообщений для компенсации удалений. Конкретная бизнес-логика описывается на языке следующим образом:
- Запрос A сначала обновить базу данных
- Сообщалось об ошибке при выполнении операции удаления в Redis, и удаление не удалось
- На этом этапе ключ Redis отправляется в очередь сообщений в качестве тела сообщения.
- После того, как система получит сообщение, отправленное из очереди сообщений, она снова удалит Redis.
Однако у этой схемы есть недостаток: она вызовет сильное вторжение в бизнес-код и тесно связана друг с другом, поэтому на данный момент будет оптимизированная схема Мы знаем, что сможем найти ее в журнале binlog после обновления. операция базы данных Mysql.Соответствующая операция, то мы можем подписаться на журнал binlog базы данных Mysql для работы с кешем.
Суммировать
Каждая схема имеет свои преимущества и недостатки.Например, во второй схеме сначала удалите кеш, а затем обновите базу данных.Наконец мы обсудили, что когда вы хотите обновить Redis, проблема может быть решена путем форсирования запроса к основной базе данных, то такая операция вызовет много бизнес-кода.Вторжение, но не требует увеличения системы, не требует увеличения сложности общего обслуживания. В последнем решении мы, наконец, обсудили использование подписки на журналы binlog для создания независимой системы для работы с Redis, Недостатком этого является то, что это увеличивает сложность системы. На самом деле каждый выбор требует от нас оценки нашего бизнеса, и ни одна технология не является универсальной для всех предприятий. Нет лучшего, только лучшее для нас.