Ax2012. Кэширование с использованием SysGlobalObjectCache и SysGlobalCache

Использование класса SysGlobalObjectCache для кэширования

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

Класс SysGlobalObjectCache, запущенный на AOS, использует тот же кэш, что и все клиентские сессии, присоединенные к данному AOS. Каждая запись, которая помещена в SysGlobalObjectCache доступна множеству сессий, которые находятся в одном процессе. Если на AOS добавлена запись кэша, все сеансы на одном и том же AOS имеют доступ к этой записи. Однако, не все кэшированные записи буду автоматически отправляться клиенту при подключении к данному AOS. Записи также не будут отправлены другим AOS, которые являются часть общей системы. Если запись была добавлена на клиенте, то запись также будет отправлена на AOS. Поэтому любые сеансы, подключенные к данному AOS, смогут найти эту запись в кэше на AOS. Любой код, который ищет запись в кэше, должен обрабатывать случай, когда запись кэша в кэше может отсутствовать. Это демонстрируется в примере ниже, где вызывается метод find и если запись не была найдена, то запись вставляется в кэш.

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

Обслуживание кэша

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

Методы:

clear — метод, который очищает кэш для одной области.

clearAllCaches – статический метод, который очищает записи кэша для всех областей.

remove – метод, который удаляет один ключ внутри одной области. Значение, которое связано с данным ключом также удаляется.

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

Область внутри кэша

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

Решение заключается в том, чтобы ваша организация использовала хорошо спланированные значения для параметра области метода вставки класса SysGlobalObjectCache:

public void
insert( 
     GlobalObjectCacheScope  scope, 
     container               key, 
     container               value
      )

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

Техника для групп подкласса

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

Все следующие ключи являются действительными и уникальными, но ниже показаны два ключа, которые неформально сгруппированы в подкласс, который называется CommerceLaw:

[2] и [5]

[‘CommerceLaw’, 2] и [‘CommerceLaw’, 5]

В предыдущем списке ключ [‘CommerceLaw’, 5] представляет собой контейнер с двумя элементами. Ключи ограничены максимум пятью пунктами. Кроме того, ключи не могут содержать другие контейнеры или буферы таблиц. Контейнер для параметра значения не подпадает под эти ограничения. Метод может работать на одном уровне, но он не может работать только с одной группой подкатегорий, такой как «CommerceLaw».

Сценарий

Предположим, что несколько сессий должны получить доступ к записям данных о наиболее активных клиентах. Операторы выбора X++ SQL от этих клиентов содержат критерии выбора, которые проверяют поле в таблице. Критерии ограничивают количество возвращаемых записей до нуля или единицы. Различные клиенты неоднократно выбирают одни и те же записи для наиболее активных клиентов.

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

    Пример

// Таблица MyCustTable имеет настроенное свойство
// CacheLookup = None, и не индексированные
// поля AccountNum and BankAccount.
//
public CustBankAccountId getCustBankAccountId(
    CustAccount            _edtCustAccount,
    GlobalObjectCacheScope _sScopeTestCache3Job)
{
    MyCustTable          tabMyCustTable;
    SysGlobalObjectCache sgoc2;
    CustBankAccountId    edtCustBankAccountId;
    container            cnResult;
    str                  sCacheGroup = "_edtCustAccount";

    sgoc2     = new SysGlobalObjectCache();
    cnResult  = sgoc2.find(_sScopeTestCache3Job,
                           [sCacheGroup, 
                            _edtCustAccount]);

    if (cnResult == conNull())
    {
        info(strFmt("Key not found in cache: %1", _edtCustAccount));
        SELECT BankAccount from tabMyCustTable
            where tabMyCustTable.AccountNum == _edtCustAccount;

        edtCustBankAccountId = tabMyCustTable.BankAccount;
        cnResult             = [edtCustBankAccountId];    
        sgoc2.insert(_sScopeTestCache3Job,
                    [sCacheGroup,
                     _edtCustAccount],
                    cnResult);
    }
    else 
    {
        info(strFmt("Ключ найден в кэше: %1", _edtCustAccount));
        edtCustBankAccountId = conPeek(cnResult, 1);
    }
    
    return edtCustBankAccountId;
}

Для проверки работы кэша, запустите job ниже.

static void TestCache3Job(Args _args) // X++ job.
{
    SysGlobalObjectCache         sgoc2;
    AaaTestSysGlobalObjectCache  aaaTest;
    GlobalObjectCacheScope       sTestCache3Job = "sTestCache3Job";
    CustBankAccountId            edtCustBankAccountId;
    container                    cnResult;

    sgoc2 = new SysGlobalObjectCache();
    sgoc2.clear(sTestCache3Job);

    aaaTest              = new AaaTestSysGlobalObjectCache();
    edtCustBankAccountId = aaaTest.getCustBankAccountId("1102", sTestCache3Job);
    info(strFmt("A, Key == 1102, Value == : %1 %2", edtCustBankAccountId, "\r\n"));

    edtCustBankAccountId = aaaTest.getCustBankAccountId("0000", sTestCache3Job);
    info(strFmt("B, Key == 0000, Value == : %1 %2", edtCustBankAccountId, "\r\n"));

    edtCustBankAccountId = aaaTest.getCustBankAccountId("1102", sTestCache3Job);
    info(strFmt("C, Key == 1102, Value == : %1 %2", edtCustBankAccountId, "\r\n"));
    sgoc2.clear(sTestCache3Job);
}

/***** Infolog display.

Message (05:07:57 pm)

Key not found in cache: 1102

A, Key == 1102, Value == : 1234 a

Key not found in cache: 0000

B, Key == 0000, Value == :

Key is found in cache!: 1102

C, Key == 1102, Value == : 1234 a

*****/

Использование класса SysGlobalCache для кэширования

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

Доступ к кэшу можно получить:

  1. на стороне клиента — infolog.globalCache()
  2. на стороне сервера — appl.globalCache()

SysGlobalCache существует  в пределах одной сессии, не имеет механизма отслеживания за устаревшими данными, не контроля за размером кэша.

Очистка SysGlobalCache — на совести того, кто решает его использовать (он должен понимать какие изменения в системе должны этот кэш сбросить).

 

microsoft.com

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar