Эта статья в основном изучает соответствующее содержание высокой пропускной способности и безопасного кеша LRU, следующим образом.
Несколько лет назад я внедрил кэш LRU, чтобы найти его идентификатор для ключевых слов. Структура данных очень интересна, потому что требуемая пропускная способность достаточно большая, чтобы устранить проблемы с производительностью, вызванные большим количеством locks и synchronized ключевыми словами. Приложение реализовано в Java.
Я думал, что серия атомных ассигнования будет поддерживать порядок LRU и LRU в concurrenthashmap. В начале я завернул значение в запись. Запись имеет узел в цепочке LRU в списке с двумя связанными. Хвост цепи сохраняет недавно используемую запись, а узел голов хранит запись, которая может быть очищена, когда кэш достигает определенного размера. Каждый узел указывает на запись, используемую для поиска.
Когда вы просматриваете значение через ключ, кэш сначала должен найти карту, чтобы увидеть, существует ли это значение. Если его не существует, он будет зависеть от загрузчика, чтобы прочитать значение из источника данных сквозь чтения и добавить его в карту в «Добавить, если отсутствует». Задача обеспечения высокой пропускной способности состоит в том, чтобы эффективно поддерживать цепь LRU. Эта параллельная хэш -карта сегментирована, а уровень потока находится на определенном уровне (вы можете указать уровень параллелизма при создании карты) не будет испытывать слишком много конкуренции потоков. Но разве цепь LRU не может быть разделена так же? Чтобы решить эту проблему, я представил вспомогательную очередь для очистки.
В кеше есть шесть основных методов. Для хитов в кешах поиск включает в себя две основные операции: Get и предложение, а для грубой потери есть четыре основных метода: получить, загрузить, положить и предлагать. В методе POT нам может потребоваться отслеживать четкую работу. Когда кэш попадает, мы пассивно проводем некоторую очистку на цепочке LRU, называемой операцией очистки.
get: вход в поиск в карте от ключа
Нагрузка: значение загрузки из источника данных
Поместите: Создайте запись и сопоставьте его в ключ
Предложение: добавьте узел в хвост списка LRU, который относится к недавно обратной записи
Выселение: удалите узлы в головке списка и связанные записи с карты (после того, как кэш достигает определенного размера)
Чистка: удалить неиспользованные узлы в списке LRU - мы называем эти узлы как отверстия, и очередь очистки отслеживает эти
Операция очистки и очистки представляют собой большие партии данных обработки. Давайте посмотрим на детали каждой операции.
Операция GET работает следующим образом:
get (k) -> v v Lookup intry by k k Если нажимает кэш, у нас есть запись e Предложение Entry e Попробуйте очистить некоторые отверстия, иначе значение нагрузки v для ключа k Создать запись e < - (k, v) Попробуйте положить e end return vaturn
Если ключ существует, мы предоставляем новый узел на хвосте цепи LRU, чтобы указать, что это недавно используемое значение. Выполнение GET и предложения не является атомной операцией (нет блокировки здесь), поэтому мы не можем сказать, что этот предлагаемый узл указывает на последнее используемое сущность, но это определенно последняя используемая сущность, полученная, когда мы выполняем одновременно. Мы не заставляем получить и предлагаем выполнять порядок между потоками, так как это может ограничить пропускную способность. После предложения узла мы стараемся сделать некоторые операции, чтобы очистить и возвращать значение. Давайте подробно рассмотрим операции по предложению и чистке.
Если произойдет потеря кэша, мы вызовым погрузчику для загрузки для этого ключа, создадим новую сущность и поместим его в карту, а операция PUT заключается в следующем:
Поместите (e) -> e существующая запись ex < - map.putifabsent (ek, e), если отсутствует вход предложения e; Если размер достигает Exict-throgold выселение некоторых записей.
Как вы можете видеть, может быть конкуренция, когда два или более потоков помещают сущность в карту, но разрешено только один успех, и предложение будет вызвано. После предоставления узла на хвосте цепочки LRU нам необходимо проверить, достиг ли кэш его порог, который является идентификатором, который мы используем для запуска операции PACTATION CLEAR. В этом конкретном сценарии приложения настройка порога меньше емкости. Операция очистки происходит в небольшой партии, а не при добавлении каждого объекта. Многочисленные потоки могут участвовать в операции очистки, пока емкость кэша не достигнет своей емкости. Блокировка легко, но потоки могут быть безопасными. Очистка головного узла цепочки LRU требует удаления, что требует тщательных атомных операций, чтобы избежать многопоточных операций удаления на карте.
Эта операция предложения очень интересна. Он всегда пытается создать узел, но не пытается удалить и удалять узлы, которые больше не используются в LRU.
Предложение (e) Если хвостовой узел не обращается к записи E Присвоить текущий узел c <-en Создать новый узел n (e), новые реферики узла E, если атомный сравнение и сет, ожидайте, что C, назначьте n Добавить узел n к хвосту LRU.
Во-первых, он будет убедиться, что узел на хвосте цепи не указывает на объект, к которой был доступ, который ничем не отличается, если только все потоки часто получают доступ к одной и той же паре ключевых значений. Это создаст новый узел на хвосте цепи. Когда эта сущность отличается, прежде чем предоставить новый узел, он пытается сделать сравнение и установить операцию для объекта, что предотвратит выполнение нескольких потоков.
Поток, который успешно выделяет узлы, обеспечивает новый узел в конце цепи LRU. Эта операция такая же, как и находка в concurrentLinkedQueue. Алгоритм зависимости описан в следующей статье. Простые, быстрые и практические не блокирующие и блокирующие алгоритмы одновременных очередей. Затем поток проверит, связана ли сущность с другими узлами ранее. Если это так, старый узел не будет удален немедленно, но будет отмечен как отверстие (ссылка на ее объект будет установлена на пустоту)
Выше приведено все подробное объяснение этой статьи о высокопроизводительном и защищенном потоке кэша LRU, и я надеюсь, что это будет полезно для всех. Заинтересованные друзья могут продолжать ссылаться на другие связанные темы на этом сайте. Если есть какие -либо недостатки, пожалуйста, оставьте сообщение, чтобы указать это. Спасибо, друзья, за вашу поддержку на этом сайте!