Уведомление о переводе ИИ
Эта документация была автоматически переведена ИИ.
Кэш
Модуль кэширования NocoBase основан на библиотеке node-cache-manager и предоставляет функциональность кэширования для разработки плагинов. Система имеет два встроенных типа кэша:
- memory - Кэш в оперативной памяти на основе lru-cache, предоставляемый
node-cache-manager по умолчанию.
- redis - Кэш Redis на основе
node-cache-manager-redis-yet.
Дополнительные типы кэша можно расширять и регистрировать через API.
Базовое использование
app.cache
app.cache — это экземпляр кэша по умолчанию на уровне приложения, который можно использовать напрямую.
// Установить кэш
await app.cache.set('key', 'value', { ttl: 3600 }); // Единица измерения TTL: секунды
// Получить кэш
const value = await app.cache.get('key');
// Удалить кэш
await this.app.cache.del('key');
ctx.cache
В промежуточном ПО или операциях с ресурсами вы можете получить доступ к кэшу через ctx.cache.
async (ctx, next) => {
let data = await ctx.cache.get('custom:data');
if (!data) {
// Промах кэша, получить из базы данных
data = await this.getDataFromDatabase();
// Сохранить в кэше, срок действия 1 час
await ctx.cache.set('custom:data', data, { ttl: 3600 });
}
await next();
}
Создание пользовательского кэша
Если вам нужно создать независимый экземпляр кэша (например, с разными пространствами имен или конфигурациями), вы можете использовать метод app.cacheManager.createCache().
import { Plugin } from '@nocobase/server';
export default class PluginCacheDemo extends Plugin {
async load() {
// Создать экземпляр кэша с префиксом
const myCache = await this.app.cacheManager.createCache({
name: 'myPlugin',
prefix: 'plugin:cache:', // Все ключи будут автоматически иметь этот префикс
store: 'memory', // Использовать кэш в памяти, необязательно, по умолчанию используется defaultStore
max: 1000, // Максимальное количество элементов кэша
});
await myCache.set('user:1', { name: 'John' });
const user = await myCache.get('user:1');
}
}
Описание параметров createCache
| Параметр | Тип | Описание |
|---|
name | string | Уникальный идентификатор кэша, обязателен |
prefix | string | Необязательно, префикс для ключей кэша, используется для предотвращения конфликтов ключей |
store | string | Необязательно, идентификатор типа хранилища (например, 'memory', 'redis'), по умолчанию используется defaultStore |
[key: string] | any | Другие пользовательские параметры конфигурации, связанные с хранилищем |
Получение созданного кэша
const myCache = this.app.cacheManager.getCache('myPlugin');
Основные методы кэша
Экземпляры кэша предоставляют обширные методы для работы с кэшем, большинство из которых унаследованы от node-cache-manager.
get / set
// Установить кэш со сроком действия (единица измерения: секунды)
await cache.set('key', 'value', { ttl: 3600 });
// Получить кэш
const value = await cache.get('key');
del / reset
// Удалить отдельный ключ
await cache.del('key');
// Очистить весь кэш
await cache.reset();
wrap
Метод wrap() — это очень полезный инструмент, который сначала пытается получить данные из кэша. Если кэш не содержит данных (промах кэша), он выполняет функцию и сохраняет результат в кэше.
const data = await cache.wrap('user:1', async () => {
// Эта функция выполняется только при промахе кэша
return await this.fetchUserFromDatabase(1);
}, { ttl: 3600 });
Массовые операции
// Массовая установка
await cache.mset([
['key1', 'value1'],
['key2', 'value2'],
['key3', 'value3'],
], { ttl: 3600 });
// Массовое получение
const values = await cache.mget(['key1', 'key2', 'key3']);
// Массовое удаление
await cache.mdel(['key1', 'key2', 'key3']);
keys / ttl
// Получить все ключи (примечание: некоторые хранилища могут не поддерживать это)
const allKeys = await cache.keys();
// Получить оставшееся время жизни ключа (единица измерения: секунды)
const remainingTTL = await cache.ttl('key');
Расширенное использование
wrapWithCondition
wrapWithCondition() похож на wrap(), но позволяет решить, использовать ли кэш, на основе условий.
const data = await cache.wrapWithCondition(
'user:1',
async () => {
return await this.fetchUserFromDatabase(1);
},
{
// Внешние параметры контролируют, использовать ли результат из кэша
useCache: true, // Если установлено в false, функция будет выполнена повторно, даже если кэш существует
// Решить, кэшировать ли на основе результата данных
isCacheable: (value) => {
// Например: кэшировать только успешные результаты
return value && !value.error;
},
ttl: 3600,
},
);
Операции с кэшем объектов
Когда кэшируемое содержимое является объектом, вы можете использовать следующие методы для непосредственной работы со свойствами объекта, не извлекая весь объект.
// Установить свойство объекта
await cache.setValueInObject('user:1', 'name', 'John');
await cache.setValueInObject('user:1', 'age', 30);
// Получить свойство объекта
const name = await cache.getValueInObject('user:1', 'name');
// Удалить свойство объекта
await cache.delValueInObject('user:1', 'age');
Регистрация пользовательского хранилища
Если вам нужно использовать другие типы кэша (например, Memcached, MongoDB и т. д.), вы можете зарегистрировать их с помощью app.cacheManager.registerStore().
import { Plugin } from '@nocobase/server';
import { redisStore, RedisStore } from 'cache-manager-redis-yet';
export default class PluginCacheDemo extends Plugin {
async load() {
// Зарегистрировать хранилище Redis (если оно еще не зарегистрировано в системе)
this.app.cacheManager.registerStore({
name: 'redis',
store: redisStore,
close: async (redis: RedisStore) => {
await redis.client.quit();
},
// Конфигурация подключения Redis
url: 'redis://localhost:6379',
});
// Создать кэш, используя только что зарегистрированное хранилище
const redisCache = await this.app.createCache({
name: 'redisCache',
store: 'redis',
prefix: 'app:',
});
}
}
Важные замечания
- Ограничения кэша в памяти: При использовании хранилища
memory убедитесь, что вы установили разумный параметр max, чтобы избежать переполнения памяти.
- Стратегия инвалидации кэша: При обновлении данных не забывайте очищать соответствующий кэш, чтобы избежать устаревших данных.
- Соглашения об именовании ключей: Рекомендуется использовать осмысленные пространства имен и префиксы, например,
module:resource:id.
- Настройки TTL: Устанавливайте TTL разумно, исходя из частоты обновления данных, чтобы сбалансировать производительность и согласованность.
- Подключение Redis: При использовании Redis убедитесь, что параметры подключения и пароль правильно настроены в производственной среде.