Я не понимаю эти вопросы интервью Redis, как я могу получить предложение?

Redis

Сегодня давайте поделимся некоторыми общими вопросами интервью Redis:

Как исправить лавину кеша?

Как решить проблему проникновения в кеш?

Как обеспечить согласованность между кэшем и двойной записью базы данных?

1. Лавина кеша

1.1 Что такое Cache Avalanche?

Напомним, почему мы используем кеш (Redis):


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


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

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

Это кеш-лавина:

Redis зависает, и все запросы уходят в базу данных.

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

Если произойдет кеш-лавина, это, вероятно, приведет к выходу из строя нашей базы данных и всей службы!

1.2 Как решить проблему лавины кеша?

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

Решение: добавьте случайное значение к сроку действия при кэшировании, что одновременно значительно сократит срок действия кэша.

Для ситуации «Redis зависает, все запросы уходят в базу» у нас могут быть следующие идеи:

До инцидента: осознайте высокую доступность Redis (архитектура master-slave + Sentinel или Redis Cluster) и постарайтесь избежать ситуации, когда Redis зависает.

Во время инцидента: на случай, если Redis действительно зависнет, мы можем настроить локальный кеш (ehcache) + текущее ограничение (hystrix), чтобы максимально избежать уничтожения нашей базы данных (по крайней мере, чтобы гарантировать, что наш сервис все еще может нормально работать)

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

2. Проникновение в кэш

2.1 Что такое проникновение в кеш?

Например, у нас есть таблица базы данных с идентификаторами, начинающимися с 1 (положительные числа):

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

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

Это проникновение в кеш:

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

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

2.1 Как решить проблему проникновения в кеш?

Есть также два решения для решения проблемы проникновения в кеш:

Поскольку запрошенные параметры являются недопустимыми (каждый раз запрашиваются несуществующие параметры), мы можем использовать фильтр Блума или фильтр сжатия для предварительного перехвата, и если это недопустимо, запрос не будет отправлен на уровень базы данных!

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

В этом случае мы обычно устанавливаем короткий срок действия для пустого объекта.


3. Кэш согласуется с двойной записью базы данных

3.1 Для операций чтения процесс выглядит следующим образом

При разговоре о проникновении в кеш выше также было упомянуто: если данные из базы не найдены, они не будут записаны в кеш.

В общем, у нас есть такая фиксированная процедура для операций чтения:

Если наши данные в кеше, то берем напрямую кеш.

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

Наконец, верните данные в запрос

3.2 В чем проблема согласованности двойной записи между кешем и базой данных?

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

Несоответствие здесь относится к несоответствию между данными в базе данных и данными в кеше.

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

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

3.3 Для операций обновления

В общем, при выполнении операции обновления у нас есть два варианта:

Сначала работайте с базой данных, затем работайте с кешем

Сначала работайте с кешем, затем работайте с базой данных

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

Итак, если атомарность нарушена, может произойти следующее:

Операция базы данных прошла успешно, но операция кэша не удалась.

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

Если первый шаг не удался, мы просто возвращаем Exception и выходим, а второй шаг вообще не будет выполняться.

Давайте проанализируем его подробно.

3.3.1 Операционный кэш

Также есть два варианта работы с кешем:

обновить кеш

удалить кеш

Как правило, мы используем стратегию удаления кэша кэша по следующим причинам:

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

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

Исходя из этих двух пунктов рекомендуется удалять кеш при его обновлении!

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

Нормальная ситуация такова:

Сначала работайте с базой данных, успех;

Потом удалите кеш, тоже успешно;

Если атомарность нарушена:

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

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

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

Кэш просто не удалось

Поток A запрашивает базу данных и получает старое значение

Поток B записывает новое значение в базу данных

Поток B удаляет кеш

Поток A записывает старое найденное значение в кеш

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

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

Для этой стратегии это на самом деле шаблон проектирования: Cache Aside Pattern

Решение проблемы с удалением кеша:

Отправить удаляемый ключ в очередь сообщений

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

Продолжайте повторять операцию удаления, пока она не завершится успешно

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

Нормальная ситуация такова:

Сначала удалите кеш, успех;

Затем обновите базу данных, это также успешно;

Если атомарность нарушена:

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

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

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

Поток A удаляет кеш

Поток B запрашивает и обнаруживает, что кэш больше не существует

Поток B обращается к базе данных для запроса, чтобы получить старое значение

Поток B записывает старое значение в кеш

Поток A записывает новое значение в базу данных

Таким образом, это также приведет к несогласованности между базой данных и кешем.

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

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

3.4 Сравнение двух стратегий

Мы можем обнаружить, что обе стратегии имеют свои преимущества и недостатки:

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

Неудовлетворительная производительность при высокой степени параллелизма, отличная производительность при нарушении атомарности.

Сначала обновите базу данных, а затем удалите кеш (шаблон проектирования Cache Aside Pattern).

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

3.5 Другие схемы и материалы для обеспечения согласованности данных

Вы можете использовать шину данных или канал Али для отслеживания обновлений binlog.

В конце концов

Вот несколько общих вопросов для интервью с Redis, я надеюсь, что вы будете полезны после прочтения и получите предложение без проблем!