Что делать, если кеш проникает?

Java

В современной архитектуре Интернета почти в каждом Интернет-проекте будет внедрена система кэширования, такая как Redis и Memcached. Для защиты нижестоящих баз данных и улучшения параллелизма системы. Независимо от того, какая система кэширования используется, можно столкнуться спроникновение в кешЭта проблема.

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

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

  • Емкость кеш-системы ограничена, и невозможно хранить все данные в системе, поэтому при запросе некэшированных данных будет происходить проникновение в кеш.
  • С другой стороны, основываясь на «принципе 208», мы обычно кэшируем только 20% часто используемых горячих данных.

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

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

Кэшировать пустые значения

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

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

Object nullValue = new Object();
try {
  Object valueFromDB = getFromDB(uid); //从数据库中查询数据
  if (valueFromDB == null) {
    cache.set(uid, nullValue, 10);   //如果从数据库中查询到空值,就把空值写入缓存,设置较短的超时时间
  } else {
    cache.set(uid, valueFromDB, 1000);
  }
} catch(Exception e) {
  cache.set(uid, nullValue, 10);
}

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

Используйте фильтр Блума

В 1970 году Блум предложил алгоритм фильтра Блума для определения того, входит ли элемент в набор. Нижний слой фильтра Блума представляет собой очень большой битовый массив. Значение по умолчанию — 0. Элемент сопоставляется с этим битовым массивом с помощью нескольких хэш-функций, и 0 изменяется на 1. Фильтр Блума нам, конечно, реализовывать не нужно, фильтр Блума есть в пакете Google guava, заинтересованные партнеры могут его изучить.

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

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

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

使用布隆过滤器示意图

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

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

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

наконец

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

互联网平头哥