Что такое диспетчер кеша

Обновлено: 01.07.2024

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

Возможности

  • Простой способ поместить любую функцию в кеш.
  • Многоуровневые кэши: данные сохраняются в каждом кэше и сначала извлекаются из кэша(ов) с наивысшим приоритетом.
  • Используйте любой кеш, если он имеет тот же API.
  • 100 процентное покрытие тестами через мокко, стамбул и синон.

Пример Express.js

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

Установка

Системы магазина

Обзор

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

<р>. вместо этого вы можете использовать функцию переноса:

Во-вторых, node-cache-manager имеет встроенный кэш памяти (с использованием node-lru-cache) со стандартными функциями, которые вы ожидаете от большинства кэшей:

В-третьих, node-cache-manager позволяет настроить многоуровневую стратегию кэширования. В большинстве случаев это может иметь ограниченное применение, но представьте себе сценарий, в котором вы ожидаете тонны трафика и не хотите использовать свой основной кеш (например, Redis) для каждого запроса. Вы решаете хранить наиболее часто запрашиваемые данные в кэше в памяти, возможно, с очень коротким временем ожидания и/или небольшим ограничением размера данных. Но вы по-прежнему хотите хранить данные в Redis для резервного копирования и для запросов, которые не так распространены, как те, которые вы хотите хранить в памяти. Это то, с чем node-cache-manager справляется легко и прозрачно.

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

Примеры использования

См. примеры ниже и в каталоге примеров. См. examples/redis_example для примера того, как реализовать кэш-хранилище Redis с пулом соединений.

Один магазин

Время жизни также можно вычислить динамически, передав функцию. Например,

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

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

Подробнее см. модульные тесты в caching.unit.js.

Пример установки/получения нескольких ключей с помощью mset() и mget()

Пример использования промисов

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

Пример использования async/await

Подсказка: следует обернуть вызов await с помощью try - catch, чтобы обработать ошибку промиса.

Пример использования экспресс-приложения

Пользовательские магазины

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

Несколько магазинов

Указание того, что кэшировать в функции переноса

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

ПРИМЕЧАНИЕ. Функции set в кэшировании и мультикэшировании не используют isCacheableValue .

Например, если вы не хотите кэшировать false и null , вы можете передать такую ​​функцию:

Затем передайте его в кеширование следующим образом:

И передать его в мультикэширование следующим образом:

Обновить ключи кеша в фоновом режиме

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

Если установлено значение refreshThreshold и доступен метод ttl для используемого хранилища, после извлечения значения из кеша будет проверен TTL.Если оставшийся TTL меньше, чем refreshThreshold , система создаст фоновый рабочий процесс для обновления значения, следуя тем же правилам, что и стандартная выборка. Тем временем система будет возвращать старое значение до истечения срока действия.

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

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

Например, передайте refreshThreshold для кэширования следующим образом:

Вы можете отключить реальное кэширование, но при этом все функции обратного вызова будут работать, установив значение none store.

Чтобы создать документацию JSDOC 3:

Тесты

Чтобы запустить тесты, сначала запустите:

Запустите тесты и JShint:

Добавить

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

Обсуждение последних новых функций, добавленных в CacheManager, и краткий обзор текущей работы.

Что делать, если Redis перестает работать — как обеспечить работоспособность приложения 09 04 2017

В выпуске 146 возник интересный вопрос по репозиторию CacheManager. Что делать, если сервер Redis умирает и может некоторое время быть в автономном режиме? Можем ли мы просто продолжить работу с кешем в памяти и подождать, пока Redis вернется в оперативный режим? И если да, то как мне это сделать с помощью CacheManager.

Одностраничное приложение Todo с CacheManager 2015-04-11

Документация

Начало работы

Краткое руководство по началу работы с CacheManager.

Основные функции и архитектура CacheManager

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

Конфигурация

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

Операции обновления

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

Сериализация

Подробное описание того, как использовать и настраивать сериализацию значений кеша в CacheManager.

Синхронизация кэша

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

Ведение журнала

Подробное описание того, как работает ведение журнала в CacheManager и как его можно использовать, с многочисленными примерами кода и вывода журнала.

Ознакомительные сведения о CacheManager

Информация о CacheManager.

Поддерживаемые технологии кэширования

Дескриптор словаря

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

Кэш памяти

Редис

Redis можно использовать как чрезвычайно быстрое и надежное автономное (или распределенное) решение.

Реализация Redis основана на популярном пакете StackExchange.Redis.

Мемкэш

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

Couchbase

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

Наш пакет Web NuGet также поставляется с настраиваемым OutputCacheProvider.

Возможности

Строгая типизация

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

Конфигурация

Существуют различные варианты настройки CacheManager:

Несколько слоев

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

Безопасное обновление

В распределенных сценариях обновление значения часто требует осторожности из-за параллелизма. CacheManager скрывает сложность и позволяет реализовать все это в одной строке кода.

Сериализация

Технологию сериализации, используемую для сериализации значений в распределенных сценариях, можно настроить.

Например, выберите сериализацию Binary-, JSON- или Protocol Buffer.

Синхронизация

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

Расширяемое ведение журнала

В конфигурацию можно добавить ведение журнала для регистрации некоторых или всех операций.

Установите пакет Microsoft.Extensions.Logging, чтобы использовать все дополнительные функции.

Кроссплатформенность

События

Интерфейс CacheManager также предоставляет события, на которые вы можете подписаться, для многих операций.

Гибкий срок действия

С помощью конфигурации вы можете установить режим и время истечения срока действия по умолчанию для каждого слоя.

Настройки срока действия также можно изменить индивидуально для каждого элемента в любой момент.

Регионы/Категории

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

Статистика/счетчики

Собирайте статистическую информацию и при необходимости отслеживайте операции кэширования в системном мониторе.

Модульный дизайн

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

Масштабируемость

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

Начните с простого подхода в памяти, а затем масштабируйте его до Redis или других распределенных решений!

Примите участие

Сообщите о проблеме, предложении или запросе функции или отправьте PR на GitHub!

Вы можете публиковать любые технические вопросы на Stack Overflow.

Или просто оставьте сообщение в комментариях ниже!.

Документация

На этом сайте доступно множество статей и примеров кода (и еще больше)

Примеры кода

Различные способы инициализации CacheManager:

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

В первом примере используется CacheFactory .

Вместо этого вы также можете создать экземпляр ConfigurationBuilder .

Или вы создаете экземпляр CacheManagerConfiguration и вызываете свойство Builder для изменения конфигурации.

Загрузить конфигурацию из JSON:

В этом примере используются расширения Microsoft.Extensions.Configuration и CacheManager.

Использование In-Memory и Redis:

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

При использовании Ehcache кеш содержит элементы, представленные в виде пар "ключ-значение". Ключ и его значение являются объектами Java. Помните о следующих моментах в отношении пар ключ-значение в кеше:

Ключ может относиться к объекту Java любого типа, кроме документа IS.

Значение может относиться к любому типу объекта Java.

Если вы кэшируете данные в BigMemory или Terracotta Server Array или записываете кэш в локальное дисковое хранилище, объекты должны быть сериализуемыми.

Примечание.
Реализаторы IData сериализуемы и поэтому могут быть включены в кэш как значение. Однако сам IData должен содержать сериализуемые объекты. Если IData, подлежащий кэшированию, включает несериализуемые объекты, такие как потоки, узлы XML или пользовательские объекты, которые не сериализуемы, Terracotta выдает исключение при попытке записи в кэш.

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

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

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

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

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

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

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

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

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

Поддерживает "подсказки", передаваемые приложениями во время открытия файла (например, произвольный или последовательный доступ, создание временного файла и т. д.)

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

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

Единый централизованный системный кэш

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

Диспетчер памяти

Один необычный аспект диспетчера кеша заключается в том, что он никогда не знает, сколько кэшированных данных фактически находится в физической памяти. Это утверждение может показаться странным, потому что цель кэша — хранить подмножество часто используемых данных в физической памяти, чтобы повысить производительность ввода-вывода. Причина, по которой диспетчер кеша не знает, сколько данных находится в физической памяти, заключается в том, что он получает доступ к данным, отображая представления файлов в системные виртуальные адресные пространства, используя стандартные объекты раздела (объекты сопоставления файлов в терминологии Windows API). (Объекты раздела являются базовым примитивом диспетчера памяти и подробно объясняются в главе 7.) При доступе к адресам в этих отображаемых представлениях диспетчер памяти страниц в блоках, которые не находятся в физической памяти. А когда требуется память, диспетчер памяти выгружает данные из кеша и обратно в файлы, открытые в кеше (сопоставленные с ним).

За счет кэширования на основе виртуального адресного пространства с сопоставленными файлами диспетчер кеша избегает генерации пакетов запроса ввода-вывода (IRP) на чтение или запись для доступа к данным кэшируемых файлов. Вместо этого он просто копирует данные в виртуальные адреса или из них, где отображается часть кэшированного файла, и полагается на диспетчер памяти, который по ошибке вводит (или извлекает) данные в (или из) памяти по мере необходимости. Этот процесс позволяет диспетчеру памяти делать глобальные компромиссы между тем, сколько памяти отдать системному кешу, а сколько — пользовательским процессам. (Диспетчер кэша также инициирует операции ввода-вывода, такие как отложенная запись, описанная далее в этой главе; однако для записи страниц он вызывает диспетчер памяти.) Кроме того, как вы узнаете из следующего раздела, такая схема позволяет процессам, открывающим кэшированные файлы, видеть те же данные, что и процессам, отображающим те же файлы в свои пользовательские адресные пространства.

Когерентность кэша

Одна из важных функций диспетчера кеша — гарантировать, что любой процесс, обращающийся к кэшированным данным, получит самую последнюю версию этих данных. Проблема может возникнуть, когда один процесс открывает файл (и, следовательно, файл кэшируется), в то время как другой процесс напрямую отображает файл в свое адресное пространство (используя функцию Windows MapViewOfFile). Эта потенциальная проблема не возникает в Windows, поскольку и диспетчер кэша, и пользовательские приложения, отображающие файлы в свои адресные пространства, используют одни и те же службы сопоставления файлов управления памятью. Поскольку диспетчер памяти гарантирует наличие только одного представления каждого уникального сопоставленного файла (независимо от количества объектов-разделов или сопоставленных представлений), он отображает все представления файла (даже если они перекрываются) с одним набором страниц в физической памяти. памяти, как показано на рис. 11-1.(Дополнительную информацию о том, как диспетчер памяти работает с отображаемыми файлами, см. в главе 7.)

Рисунок 11-1. Согласованная схема кэширования

Так, например, если процесс 1 имеет представление (представление 1) файла, сопоставленное с его адресным пространством пользователя, а процесс 2 обращается к тому же представлению через системный кэш, процесс 2 увидит любые изменения, внесенные процессом 1. как они сделаны, а не как они смыты. Диспетчер памяти не будет сбрасывать все отображаемые пользователем страницы, а только те, которые, как ему известно, были записаны (поскольку для них установлен модифицированный бит). Таким образом, любой процесс, обращающийся к файлу в Windows, всегда видит самую последнюю версию этого файла, даже если некоторые процессы открыли файл через систему ввода-вывода, а другие отобразили файл в свое адресное пространство с помощью Windows. функции сопоставления файлов.

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

Виртуальное кэширование блоков

Многие диспетчеры кэша операционных систем (включая Novell NetWare, OpenVMS и более старые системы UNIX) кэшируют данные на основе логических блоков. С помощью этого метода диспетчер кеша отслеживает, какие блоки раздела диска находятся в кеше. Диспетчер кеша Windows, напротив, использует метод, известный как кэширование виртуальных блоков, при котором диспетчер кеша отслеживает, какие части каких файлов находятся в кеше. Диспетчер кеша может отслеживать эти части файлов, отображая представления файлов размером 256 КБ в системные виртуальные адресные пространства, используя специальные процедуры системного кеша, расположенные в диспетчере памяти. Этот подход имеет следующие основные преимущества:

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

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

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

Потоковое кэширование

Диспетчер кеша также предназначен для кэширования потоков , а не кэширования файлов. Поток — это последовательность байтов в файле. Некоторые файловые системы, такие как NTFS, позволяют файлу содержать более одного потока; диспетчер кеша приспосабливается к таким файловым системам, независимо кэшируя каждый поток. NTFS может использовать эту возможность, организуя свою основную таблицу файлов (описанную в главе 12) в потоки, а также кэшируя эти потоки. На самом деле, хотя можно сказать, что менеджер кэша кэширует файлы, на самом деле он кэширует потоки (все файлы имеют по крайней мере один поток данных), идентифицируемые как именем файла, так и, если в файле существует более одного потока, именем потока.

Поддержка восстанавливаемой файловой системы

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

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

Файловая система записывает запись в файл журнала, в которой документируется обновление тома, которое она намеревается выполнить.

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

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

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

Когда файловая система записывает данные в кеш, она может указать логический порядковый номер (LSN), который идентифицирует запись в файле журнала, соответствующую обновлению кеша. Диспетчер кэша отслеживает эти числа, записывая самые низкие и самые высокие номера LSN (представляющие самые старые и самые новые записи файла журнала), связанные с каждой страницей в кэше. Кроме того, потоки данных, защищенные записями журнала транзакций, помечаются NTFS как «запрещенные для записи», чтобы средство записи сопоставленных страниц не могло непреднамеренно записать эти страницы до того, как будут записаны соответствующие записи журнала. (Когда модуль записи отображаемой страницы видит страницу, помеченную таким образом, он перемещает страницу в специальный список, который диспетчер кеша затем сбрасывает в соответствующее время, например, когда происходит отложенная запись.)

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

Читайте также: