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

Победа принадлежит самым упорным. — Наполеон Бонапарт, французский военный и политический деятель
система каталогов
Давайте сначала кратко рассмотрим эту общую систему каталогов.
Сегодня я познакомлю вас с пятью аспектами использования кэша, включая принципы, практику, технический выбор и общие проблемы.
Эта система каталогов подобна человеческому скелету.Только заполнив все виды внутренних органов, органов и плоти и крови, красота кеша может ожить на бумаге. Далее я приглашаю всех сделать это вместе со мной.
Не будем останавливаться на Hello World, поговорим о кэшировании.
О кэшировании
What
Что такое кеш?
Кэширование — очень часто используемый метод повышения производительности на практике.
В java так называемый кеш предназначен для хранения в памяти объектов, которые программа или система часто вызывает, и объекты могут быть быстро получены из памяти при повторном их вызове, без необходимости создавать новые и повторяющиеся экземпляры.
Это может снизить нагрузку на систему и повысить ее эффективность.
В настоящее время существует два режима кэширования:
-
Кэш памяти: Кэшированные данные хранятся в памяти сервера.
优点:速度快。 缺点:资源有限。
-
Файловый кэш: Кэшированные данные хранятся на жестком диске сервера.
优点:容量大。 缺点:速度偏慢,尤其在缓存数量巨大时。
why
Зачем использовать кеш?
Самый лаконичный ответ, который я видел на вопрос, почему используется кэширование, звучит так: из мечты построить социалистическое общество как можно быстрее и дешевле.
Но это очень противоречивое утверждение, как будто вы не высоки, богаты и красивы и хотите выйти замуж за Бай Фумэя, это кажется дурацкой мечтой.
Поскольку большее не может быть быстрым, хорошее не может спасти, как мы можем сделать больше и быстрее, хорошо и сэкономить?
Ответ заключается в использовании кеша!
Поговорим о том, как использовать кеш для реализации этой мечты.
Прежде всего, я хотел бы сначала заявить, что я думаю о таком обмене.
На самом деле, от первого использования целочисленного кеша Java до понимания прокси-кеша CDN, от первого контакта со встроенным кешем запросов MySQL до использования Redis для кэширования сеанса, я все больше и больше осознавал важность и повсеместность использования кеша.
Поэтому я считаю необходимым разобраться в том, чему я научился и что применил, и использовать это в своей работе на благо всех, поэтому есть такой обмен технологиями.
Прежде чем мы поговорим о кэшировании, давайте поговорим о базах данных.
Кроме того, удаление и модификация, запросы к базе данных составляют более 80% операций с базой данных. Очень частые операции чтения с диска могут привести к чрезвычайно низкой производительности базы данных.
Важность базы данных очевидна:
- База данных обычно является основной частью корпоративной прикладной системы.
- Объем данных, хранящихся в базе данных, обычно очень велик.
- Операции запросов к базе данных часто бывают частыми, а иногда и сложными.
Мы знаем, что для большинства веб-приложений узким местом всей системы является база данных.
Причина очень проста: другие факторы в веб-приложениях, такие как пропускная способность сети, узлы балансировки нагрузки, серверы приложений (включая ЦП, память, индикаторы жесткого диска, количество подключений и т. д.), кэши, могут быть легко масштабированы по горизонтали (обычно известные как арифмометры).
Для MySQL из-за требования согласованности данных давление записи данных в базу данных не может быть рассеяно простым добавлением машин. Хотя предварительное кэширование (Redis и т. д.), разделение чтения и записи, а также подбаза данных и подтаблица могут использоваться для уменьшения нагрузки по сравнению с горизонтальным расширением других компонентов системы, оно подвержено слишком многим ограничений, что значительно усложнит систему.
Поэтому подключением, чтением и записью базы данных следует очень дорожить.
Вы можете подумать, что вам следует использовать кеш напрямую, но явно ненаучно использовать большое количество кешей вне зависимости от сцены. Мы не можем держать в руках молоток и видеть все как гвозди.
Но кеш не панацея.Кэшем надо пользоваться с осторожностью.Хорошо пользоваться кешем не просто. Поэтому мне потребовалось некоторое время, чтобы разобраться с реализацией кеша и некоторыми распространенными проблемами.
when
Во-первых, кратко рассмотрим процесс веб-запросов и роль различных кэшей узлов.
how
Давайте не будем сначала говорить о коде.Что касается того, как работает кеш, простой процесс запроса данных кеша выглядит следующим образом.
Две наиболее важные стратегии кэширования, которые следует учитывать при проектировании кэша.
- Срок службы TTL (время жизни), То есть период времени с момента создания в кеше до его истечения (он истечет вне зависимости от того, был ли доступ в этот период)
- TTI (Time To Idle) период простоя, То есть, как долго к данным не обращались, они будут удалены из кеша.
Когда мы поговорим о кэш-лавинах позже, мы поговорим о катастрофических последствиях неправильной настройки политики кэширования и о том, как их избежать, здесь мы не будем перечислять их первыми.
пользовательский кеш
Как добиться
Некоторые понятия о кэшировании были введены ранее, так сложно ли реализовать кэширование, вернее реализовать предварительно кэшированное хранилище?
Ответ: не сложно.
Сама JVM является высокоскоростным хранилищем кеша, а Java предоставляет нам потокобезопасную ConcurrentMap, которая может быть очень удобна для реализации полностью настраиваемого экземпляра кеша.
Позже вы обнаружите, что реализация Spring Cache по умолчанию, SimpleCacheManager, также проектирует свой собственный кэш таким же образом.
Вот простой код реализации, но с 36 строками реализованы основные операции, такие как сохранение, обновление, чтение и удаление кеша. В сочетании с реальным бизнес-кодом вы можете легко играть с кешем в JVM, не полагаясь на какую-либо стороннюю реализацию.
Однако я думаю, что как технарь с преследованием вы никогда не остановитесь на достигнутом.
Итак, давайте подумаем, каковы преимущества и недостатки нашей собственной реализации кэша?
По сравнению с пользовательским кешем вы можете глубже понять принципы и преимущества Spring Cache.
Здесь характеристики Spring Cache перечислены первыми, а его принцип и особенности использования будут представлены ниже.
Spring Cache
Spring Cache является абстракцией функции кэширования, предоставляемой Spring: то есть он позволяет привязывать различные решения кэширования (такие как Ehcache, Redis, Memcache, Map и т. д.), но напрямую не обеспечивает реализацию самой функции кэширования.
Поддерживает использование кэширования в режиме аннотации, что очень удобно.
Реализация Spring Cache по существу зависит от поддержки аспектов Spring AOP.
Зная принцип Spring Cache, вы будете глубже понимать использование аннотаций Spring Cache.
Spring Cache использует четыре основных аннотации.
@CacheEvict очень важен для обеспечения согласованности кеша, что будет обсуждаться позже.
В то же время Spring также поддерживает пользовательские ключи кеша и SpringEL, которые здесь подробно обсуждаться не будут, а заинтересованные студенты могут обратиться к документации Spring Cache.
Кэшированные высокие частоты
Точно так же, как хорошо написанная партитура нуждается в певце, чтобы ее спеть, чтобы она была красивой.
Как упоминалось выше, Spring Cache — это абстракция кэширования, так как же обычно используются реализации кэширования?
В певческом мире есть три основных тенора, поэтому, если бы тайный мир выбирал, кто был бы тремя основными сопрано?
Redis
Redis — это система хранения ключей и значений, похожая на Memcached.
Разница в том, что он поддерживает относительно больше типов значений для хранения, включая string (строка), list (связанный список), set (набор), zset (отсортированный набор — упорядоченный набор) и hash (тип хэша). Эти типы данных поддерживают push/pop, add/remove, объединение и разность пересечений.
Как и Memcached, для обеспечения эффективности данные кэшируются в памяти.
Отличие состоит в том, что redis будет периодически записывать обновленные данные на диск или записывать операции модификации в дополнительные файлы записей, и на этом основании добиваться синхронизации master-slave (мастер-подчиненный). Redis поддерживает синхронизацию master-slave. Данные могут быть синхронизированы с главного сервера на любое количество подчиненных серверов, которые могут быть главными серверами, связанными с другими подчиненными серверами. Это позволяет Redis выполнять репликацию одноуровневого дерева.
Данные могут быть записаны на диск преднамеренно или непреднамеренно. Поскольку механизм публикации/подписки полностью реализован, можно подписаться на канал и получить полную запись публикации сообщения с главного сервера при синхронизации дерева из любой точки базы данных.
Синхронизация полезна для масштабируемости и избыточности данных для операций чтения.
Каковы подходящие сценарии для Redis?
- Кэш сеансов. Преимущество кэширования сеансов с Redis по сравнению с другими хранилищами (такими как memcached) заключается в том, что Redis обеспечивает постоянство.
- Full Page Cache (FPC): в дополнение к базовому токену сеанса Redis также предоставляет очень простую платформу FPC.
- Очередь: одно из больших преимуществ Redis в области механизмов хранения в памяти заключается в том, что он предоставляет операции со списками и наборами, что делает Redis хорошей платформой для организации очередей сообщений.
- Таблица лидеров/счетчик: Redis отлично справляется с увеличением и уменьшением данных в памяти.
- подписаться/опубликовать
недостаток:
-
Упорство. Redis напрямую хранит данные в памяти.Чтобы сохранить данные на диск, Redis может реализовать процесс сохранения двумя способами.
Timed snapshot (моментальный снимок): Вся база данных записывается на диск через равные промежутки времени, и все данные записываются каждый раз, что очень дорого. Добавление на основе операторов (aof): отслеживаются только измененные данные, но добавляемый журнал может быть слишком большим, в то же время все операции выполняются повторно, а скорость восстановления низкая.
-
Потребление памяти слишком велико.
Ehcache
Ehcache — это зрелая структура кэширования, которую вы можете использовать непосредственно для управления своим кешем.
Инфраструктура кэширования Java EhCache EhCache — это среда внутрипроцессного кэширования на чистом языке Java с быстрыми и экономичными функциями, которая используется по умолчанию в Hibernate.
Особенности: Включить кэширование диска при нехватке памяти (maxEntriesLoverflowToDiskocalDisk настраивает Ehcache для записи объектов на диск, когда количество объектов в памяти достигает maxElementsInMemory).
Memcached
Memcached — это высокопроизводительная распределенная система кэширования объектов в памяти для динамических веб-приложений, позволяющая снизить нагрузку на базу данных. Он основан на хэш-карте, в которой хранятся пары ключ/значение.
Его демон (daemon) написан на C, но клиент может быть написан на любом языке и общаться с демоном по протоколу memcached.
Memcached повышает скорость динамических веб-сайтов, управляемых базой данных, путем кэширования данных и объектов в памяти, чтобы уменьшить количество операций чтения базы данных.
Memcached и Redis, принадлежащие к одной и той же системе хранения ключей, часто сравнивают вместе:
- Структура данных и работа Memcached относительно просты и не так богаты, как структура, поддерживаемая Redis.
- Используя простое хранилище ключей и значений, Memcached использует больше памяти, Если Redis использует хэш-структуру для хранения ключей и значений, его использование памяти будет выше, чем у Memcached, из-за комбинированного сжатия.
- Поскольку Redis использует только одно ядро, а Memcached может использовать несколько ядер, в среднем Redis имеет более высокую производительность, чем Memcached, при хранении небольших данных на каждом ядре. Для данных выше 100 КБ производительность Memcached выше, чем у Redis.Хотя Redis недавно оптимизировал производительность хранения больших данных, он все же немного уступает Memcached.
- Хотя Redis — это система хранения на основе памяти, она сама поддерживает сохранение данных в памяти и предоставляет две основные стратегии сохранения: моментальные снимки RDB и журналы AOF. Memcached не поддерживает операции сохранения данных. Memcached — это система буферизации данных с полной памятью.Хотя Redis поддерживает персистентность данных, в конце концов, полный объем памяти является основой его высокой производительности.
- В качестве системы хранения на основе памяти размер физической памяти машины представляет собой максимальный объем данных, который может хранить система. Если объем обрабатываемых данных превышает размер физической памяти одной машины, необходимо построить распределенный кластер для расширения емкости хранилища.
Сам Memcached не поддерживает распространение, поэтому распределенное хранилище Memcached может быть реализовано только на стороне клиента с помощью распределенных алгоритмов, таких как согласованное хеширование.
По сравнению с Memcached, который может реализовывать распределенное хранилище только на стороне клиента, Redis предпочитает создавать распределенное хранилище на стороне сервера. Последняя версия Redis уже поддерживает распределенное хранилище.
Расширенный кеш
Кэширование широко используется в проектах из-за высокой параллелизма и высокой производительности. Особенно в высокопараллельных, распределенных и микросервисных бизнес-сценариях и архитектурах.
Будь то высокая степень параллелизма, распределенные или микросервисы, все зависит от высокопроизводительных серверов. Когда речь идет о высокопроизводительных серверах, мы должны говорить о кэшировании.
Так называемая высокая производительность в основном отражается в высокой доступности, коротком времени обработки бизнеса и правильности данных.
Своевременная обработка данных — это вопрос «пространства во времени». Распределенная память или флэш-память и другие устройства быстрого доступа используются для замены баз данных, развернутых на обычных серверах, и файлов, хранящихся на механических жестких дисках. Это кэш для повышения производительности сервера. сущность.
Высокий параллелизм: Это один из факторов, который необходимо учитывать при проектировании архитектуры распределенной системы Интернета.Обычно это означает, что проект гарантирует, что система может обрабатывать множество запросов параллельно в одно и то же время.
распределено: Это повышает эффективность за счет сокращения времени выполнения одной задачи. Например, задача состоит из 10 подзадач, и каждая подзадача выполняется в одиночку 1 час, затем на выполнение измененной задачи на одном сервере уходит 10 часов. При использовании распределенного решения предоставляется 10 серверов, каждый сервер отвечает только за обработку одной подзадачи, независимо от зависимостей между подзадачами, выполнение задачи занимает всего один час.
Микросервисы: Первый ключевой момент, подчеркиваемый архитектурой, заключается в том, что бизнес-система должна быть полностью разделена на компоненты и обслуживаться.Исходная единая бизнес-система будет разделена на несколько небольших приложений, которые можно независимо разрабатывать, проектировать, эксплуатировать и поддерживать. Взаимодействие и интеграция между этими небольшими приложениями осуществляются через сервисы.
проблемы с когерентностью кэша
Как происходит когерентность кеша: сначала запишите базу данных, а затем удалите кеш:
第一步写数据库成功,第二步淘汰缓存失败,则会引发一次严重的缓存不一致问题。
Как избежать проблемы несогласованности кеша: сначала устранить кеш, а потом писать в базу:
第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。
Когерентность распределенного кэша
Мы используем zookeeper для координации каждого узла экземпляра кеша. Zookeeper — это служба распределенной координации, включающая набор примитивов, который может уведомлять клиента обо всех узлах наблюдения и обеспечивать соответствие порядка событий порядку, в котором клиент получает сообщения; кластер zookeeper Этот сценарий может быть реализован очень легко.
Алгоритм согласованного хеширования реализует отображение хэша из KEY на кэш-сервер через структуру данных, называемую согласованным хеш-кольцом.
Кэш Лавина
Причина 1. а. Поскольку уровень Cache несет большое количество запросов и эффективно защищает уровень Storage (обычно считается, что этот уровень имеет чуть более слабую устойчивость к давлению), количество обращений к Storage на самом деле очень мало, так что это очень круто . б) Однако, если по каким-либо причинам (время простоя, зависание службы кэширования или не отвечает) происходит сбой уровня Cache, это означает, что все запросы будут доходить до уровня Storage, и объем вызовов всего Storage резко возрастет. немного не выдерживает и даже вешает трубку
Причина 2. Мы использовали одно и то же время истечения при настройке кеша, что приводило к сбою кеша в определенный момент одновременно, все запросы переадресовывались в БД, а мгновенная нагрузка на БД была слишком тяжелой и лавинообразной.
Проблема лавин называется в зарубежных странах: пугающее стадо (убегающий бизон), что означает, что после сбоя кеша трафик ударит по бэкенду, как бегущий бизон.
решение
- Блокировки/очереди обеспечивают однопотоковую запись в кеш.
Лавинный эффект отказа оказывает ужасное влияние на основную систему.
Большинство разработчиков систем рассматривают возможность использования блокировок или очередей для обеспечения однопоточной (процессной) записи в кэш, чтобы избежать большого количества одновременных запросов, попадающих в базовую систему хранения во время аннулирования.
Очередь блокировки предназначена только для снижения нагрузки на базу данных и не повышает пропускную способность системы.
Если предположить, что при высоком уровне параллелизма ключ блокируется во время восстановления кэша, это означает, что 999 из 1000 запросов блокируются. Это также заставит пользователя ждать тайм-аута, что является временным решением!
Решением для блокировки очереди является проблема параллелизма в распределенной среде, и проблему распределенной блокировки можно решить; поток также будет заблокирован, а пользовательский опыт очень плохой! Поэтому он редко используется в реальных сценариях с высокой степенью параллелизма!
- Избегайте аннулирования кеша одновременно
Например, чтобы распределить время аннулирования кеша, мы можем добавить случайное значение в конце на основе исходного времени аннулирования.
- Деградация кэша
Когда происходит скачок трафика, возникают проблемы со службами (например, медленное время отклика или отсутствие отклика) или когда неосновные службы влияют на производительность основных процессов, все равно необходимо гарантировать, что службы по-прежнему доступны, даже с убытком.
Система может автоматически переходить на более раннюю версию в соответствии с некоторыми ключевыми данными или может быть настроена с помощью переключателей для перехода на более раннюю версию вручную.
Конечная цель перехода на более раннюю версию — сохранить доступность основных служб, даже с убытком. И некоторые услуги не могут быть понижены (например, добавление в корзину, оформление заказа).
Перед понижением системы следует разобраться, можно ли оставить систему для защиты лидера, таким образом выяснив, какие из них должны быть защищены до смерти, а какие можно понизить.
Например, вы можете обратиться к плану настройки уровня журнала:
(1) Общее: например, время ожидания некоторых служб иногда истекает из-за дрожания сети или служба находится в сети, и ее можно автоматически понизить;
(2) Предупреждение: некоторые службы колеблются в степени успешности в течение определенного периода времени (например, между 95 и 100%), который может быть автоматически понижен или вручную понижен, и будет отправлен сигнал тревоги;
(3) Ошибка: например, уровень доступности ниже 90%, или пул соединений с базой данных перегружен, или объем доступа внезапно увеличивается до максимального порога, который может выдержать система, в это время он может быть автоматически понижен. или вручную понижен в зависимости от ситуации;
(4) Серьезные ошибки: например, по особым причинам данные неверны, и в настоящее время требуется аварийный переход на более раннюю версию вручную.
Разрушение кеша / проникновение в кеш
Проникновение в кэш относится к запросу фрагмента данных, который не должен существовать.Поскольку кеш пассивно записывается, когда он отсутствует, и по причинам отказоустойчивости, если данные не могут быть найдены на уровне хранилища, они не будут записаны в кеш, что приведет к этим несуществующим данным.Каждый раз, когда данные запрашиваются, они должны идти на уровень хранения для запроса, что теряет смысл кэширования. При большом трафике БД может зависнуть, если кто-то использует несуществующий ключ для частой атаки на наше приложение, это уязвимость.
Проникновение в кэш — решение 1
Простой и грубый метод, если данные, возвращаемые запросом, пусты (независимо от того, данные не существуют или система дает сбой), мы все равно кэшируем пустой результат,
Но время его истечения будет коротким, максимум пять минут.
Проникновение в кэш — решение 2
Наиболее распространенным является использование фильтра Блума для хэширования всех возможных данных в достаточно большое растровое изображение, и данные, которые не должны существовать, будут перехвачены этим растровым изображением, что позволяет избежать нагрузки запросов на базовую систему хранения.
Например, в торговом центре есть 1 миллион пользовательских данных, и все идентификаторы пользователей перенесены на карту.
Когда приходит запрос, сначала определяем включен ли user id в карту, и напрямую возвращаем, если нет, если да, то заходим в кеш, чтобы проверить, есть ли эти данные, если есть, возвращаем, и затем проверьте базу данных, если это не так.
Это не только уменьшит нагрузку на базу данных, но и значительно уменьшит нагрузку на систему кэширования.
сообщение
Древние говорили: на бумаге вы в конечном итоге почувствуете себя мелкими, и вы должны делать это, не подозревая об этом.
Опыт и мудрость других должны быть проверены вами, чтобы знать, являются ли они истиной, и только через личную практику я могу использовать их.
Чужие знания — это всего лишь ветки, их нужно сплести в лестницу, они могут помочь вам подняться.
Ссылка на ссылку
- Энциклопедия Baidu — Кэш
- Карта разума Spring, чтобы Spring больше не было сложно понять (кэш)
- importnew : Spring Cache
- Иллюстрация эволюции распределенных архитектур
- EHCACHE
- официальная документация по ehcache
- Базовый пример начала работы с ehcache
- Подробная интерпретация ehcache
- ehcache memcache redis три тенора кеша
- Сравнение технологий кеширования сайтов ehcache memcache redis
- Сбой кеша, аннулирование и проблемы с горячими клавишами
- Пример перегрузки службы в приложении кэширования
- Фильтр Блума Фильтр Блума
- Распространенные проблемы кэширования в сценариях с высоким параллелизмом
- проблема лавинного кэша
- Давайте снова поговорим о технологии кэширования
- проблема проникновения в кеш
- Дизайн микросервисного кэша
- Гарантия согласованности кэша и базы данных
- Разбивка распределенного кеша
- Кэширование CDN
- Целочисленный механизм кэширования в ava
- кеш запросов mysql
- Используйте Spring Session и Redis для решения проблемы распределенного совместного использования сеансов между доменами.
- Изучение Spring-Session+Redis для совместного использования сессий
- Объяснение тестов MySQL и инструмента sysbench
- Разбивка распределенного кеша
- Анализ схемы непротиворечивости распределенной базы данных и кэша при двойной записи