Политика замены страниц (Replacement Policies)#

Если при включенном Native Persistence объем данных, который DataGrid хранит на диске, больше объема памяти вне heap, нужно вытеснить страницу данных из памяти Off-Heap на диск, чтобы загрузить страницу с диска в целиком заполненную память Off-Heap. Этот процесс называется заменой или ротацией страниц (page replacement, page rotation).

Когда Native Persistence выключен, вместо замены страниц используется вытеснение данных (eviction) — подробнее об этом написано в разделе «Политика вытеснения данных из кеша (Eviction Policies)».

Когда DataGrid нужна страница данных, ее поиск начинается с памяти вне heap. Если нужная страница данных не нашлась в Off-Heap, она загружается с диска. Если память вне heap переполнена, нужно выбрать другую страницу для замены (для хранения на диске и вытеснения).

Алгоритмы поиска страниц для замены:

Алгоритм по замене страниц настраивается с помощью свойства PageReplacementMode в DataRegionConfiguration. По умолчанию используется алгоритм CLOCK.

Пример настройки алгоритма замены страниц:

<bean class="org.apache.ignite.configuration.IgniteConfiguration">
  <!-- Конфигурация памяти. -->
  <property name="dataStorageConfiguration">
    <bean class="org.apache.ignite.configuration.DataStorageConfiguration">
      <property name="dataRegionConfigurations">
        <list>
          <!--
              Определение персистентного региона данных с режимом замены страниц Segmented-LRU.
          -->
          <bean class="org.apache.ignite.configuration.DataRegionConfiguration">
            <!-- Название региона данных. -->
            <property name="name" value="persistent_data_region"/>

            <!-- Включите режим Persistence. -->
            <property name="persistenceEnabled" value="true"/>

            <!-- Максимальный размер — 20 Гб (ОЗУ). -->
            <property name="maxSize" value="#{20L * 1024 * 1024 * 1024}"/>

            <!-- Включение алгоритма замены страниц SEGMENTED-LRU для данного региона. -->
            <property name="pageReplacementMode" value="SEGMENTED_LRU"/>
          </bean>
        </list>
      </property>
    </bean>
  </property>

  <!-- Остальная конфигурация. -->
</bean>
// Конфигурация узла.
IgniteConfiguration cfg = new IgniteConfiguration();

// Конфигурация памяти.
DataStorageConfiguration storageCfg = new DataStorageConfiguration();

// Создание нового региона данных.
DataRegionConfiguration regionCfg = new DataRegionConfiguration();

// Название региона.
regionCfg.setName("persistent_data_region");

// Включение режима Persistence.
regionCfg.setPersistenceEnabled(true);

// Максимальный размер — 20 Гб (ОЗУ).
regionCfg.setMaxSize(20L * 1024 * 1024 * 1024);

// Включение алгоритма замены страниц SEGMENTED-LRU для данного региона.
regionCfg.setPageReplacementMode(PageReplacementMode.SEGMENTED_LRU);

// Установка конфигурации региона данных.
storageCfg.setDataRegionConfigurations(regionCfg);

// Применение новой конфигурации.
cfg.setDataStorageConfiguration(storageCfg);

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

Алгоритм Random-LRU#

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

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

Алгоритм Segmented-LRU#

Алгоритм Segmented-LRU — устойчивый к сканированию вариант алгоритма LRU (Least Recently Used). Список страниц Segmented-LRU делится на два типа: сегмент для испытаний и защищенный сегмент. Страницы каждого сегмента упорядочены от наименее до наиболее посещаемых. Новые страницы добавляются в конец сегмента испытаний. Существующие страницы удаляются из текущего местоположения и добавляются в конец защищенного сегмента. Все страницы в нем используются как минимум два раза. У защищенного сегмента есть ограничения по размеру, поэтому переход страницы из сегмента испытаний может привести к миграции LRU-страницы из защищенного сегмента в конец сегмента испытаний. Это даст странице еще одну попытку использования перед заменой. Страница для замены выбирается из наименее посещаемых страниц сегмента испытаний.

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

Алгоритм CLOCK#

Алгоритм CLOCK хранит в памяти циклический список страниц, в котором «стрелка» (hand) указывает на последний просмотренный фрейм страницы в списке. Если происходит ошибка (страница отсутствует и пустых фреймов нет), в месте нахождения hand проверяется флаг попадания (hit flag) страницы. Если значение hit flag — 0, вместо страницы, на которую показывает hand, помещается новая, а сам указатель перемещается на одну позицию дальше. Если значение hit flag ненулевое, флаг очищается, указатель hand увеличивается и процесс повторяется до тех пор, пока не произойдет замена страницы.

У алгоритма почти нулевая стоимость обслуживания. Эффективность замены страниц CLOCK больше Random-LRU и меньше Segmented-LRU.