Skip to content

Summer缓存(二级缓存)

Summer缓存基于 Mem 缓存和 Redis 缓存实现

创建Summer缓存

比如,在模块 demo-student 中创建一个 Summer 缓存: student,用于缓存学生数据

1. Cli命令

bash
$ vona :create:bean summerCache student --module=demo-student

2. 菜单命令

TIP

右键菜单 - [模块路径]: Vona Bean/Summer Cache

Summer缓存定义

typescript
export type TSummerCacheStudentKey = string;
export interface TSummerCacheStudentData { id: string; name: string }

@SummerCache()
export class SummerCacheStudent
  extends BeanSummerCacheBase<TSummerCacheStudentKey, TSummerCacheStudentData>
  implements ISummerCacheGet<TSummerCacheStudentKey, TSummerCacheStudentData> {
  async getNative(
    key?: TSummerCacheStudentKey,
    _options?: TSummerCacheActionOptions<TSummerCacheStudentKey, TSummerCacheStudentData>,
  ): Promise<TSummerCacheStudentData | null | undefined> {
    const student = await this.scope.model.student.getById(key!);
    if (!student) return null;
    return { id: student.id as string, name: student.name };
  }
}
  • TSummerCacheStudentKey: 定义缓存 Key 的类型
  • TSummerCacheStudentData: 定义缓存 Data 的类型

getNative

读取 Summer 缓存的一般流程:

  1. 先读取 Mem 缓存
  2. 如果 Mem 缓存不存在,则读取 Redis 缓存
  3. 如果 Redis 缓存不存在,则调用getNative方法
    • 比如,在getNative方法中查询 db 数据

mgetNative

可以提供mgetNative方法支持同时读取多个缓存

如果没有提供mgetNative方法,在同时读取多个缓存时,系统会自动循环调用mgetNative方法

diff
export class SummerCacheStudent
  extends BeanSummerCacheBase<TSummerCacheStudentKey, TSummerCacheStudentData>
  implements
    ISummerCacheGet<TSummerCacheStudentKey, TSummerCacheStudentData>,
+   ISummerCacheMGet<TSummerCacheStudentKey, TSummerCacheStudentData> {
  async getNative(
    key?: TSummerCacheStudentKey,
    _options?: TSummerCacheActionOptions<TSummerCacheStudentKey, TSummerCacheStudentData>,
  ): Promise<TSummerCacheStudentData | null | undefined> {
    ...
  }

+ async mgetNative(
+   keys: TSummerCacheStudentKey[],
+   _options?: TSummerCacheActionOptions<TSummerCacheStudentKey, TSummerCacheStudentData>,
+ ): Promise<Array<TSummerCacheStudentData | null | undefined>> {
+   const students = await this.scope.model.student.mget(keys);
+   return students.map(student => {
+     return { id: student.id as string, name: student.name };
+   });
+ }
}

Summer缓存参数

可以为 Summer 缓存配置参数

typescript
@SummerCache({
  preset: 'all',
  mode: 'all',
  mem: {
    max: 500,
    ttl: 2 * 3600 * 1000,
  },
  redis: {
    ttl: 2 * 3600 * 1000,
  },
  ignoreNull: false,
})
class SummerCacheStudent {}
名称类型默认值说明
preset'all' | 'mem' | 'redis'预定义配置,是mode/mem/redis参数的组合
mode'all' | 'mem' | 'redis''all'缓存模式
memMem 缓存的配置
redisRedis 缓存的配置
ignoreNullbooleanfalse是否忽略null值。当ignoreNull=true时,如果从Mem缓存/Redis缓存中读取的数据为null则忽略掉,然后调用getNative/mgetNative方法获取新值
  • mode
名称说明
all使用 Mem 缓存和 Redis 缓存
mem仅使用Mem 缓存
redis仅使用Redis 缓存

App Config

可以在 App Config 中配置 Summer 缓存参数

src/backend/config/config/config.ts

typescript
// onions
config.onions = {
  summerCache: {
    'demo-student:student': {
      preset: 'all',
      mode: 'all',
      mem: {
        max: 500,
        ttl: 2 * 3600 * 1000,
      },
      redis: {
        ttl: 2 * 3600 * 1000,
      },
      ignoreNull: false,
    },
  },
};

Summer缓存启用/禁用

可以控制 Summer 缓存的启用/禁用

1. Enable

src/backend/config/config/config.ts

diff
// onions
config.onions = {
  summerCache: {
    'demo-student:student': {
+     enable: true,
    },
  },
};

2. Meta

可以让 Summer 缓存在指定的运行环境生效

名称类型说明
flavorstring|string[]参见: 运行环境与Flavor
modestring|string[]参见: 运行环境与Flavor
  • 举例
diff
@SummerCache({
+ meta: {
+   flavor: 'normal',
+   mode: 'dev',
+ },
})
class SummerCacheStudent {}

使用Summer缓存

typescript
class ControllerStudent {
  @Web.get('test')
  async test() {
    const studentByDb = await this.scope.model.student.getById('2');
    const studentBySummer = await this.scope.summerCache.student.get('2');
    assert.equal(studentByDb?.id, studentBySummer?.id);
    assert.equal(studentByDb?.name, studentBySummer?.name);
  }
}
  • this.scope.summerCache.student: 通过模块 scope 取得缓存实例

缓存方法参数

get方法为例介绍缓存方法的参数

typescript
await this.scope.summerCache.student.get('2', {
  ttl: 2 * 3600 * 1000,
  broadcastOnSet: 'del',
  updateAgeOnGet: true,
  ignoreNull: false,
  mode: 'all',
  force: false,
  disableTransactionCompensate: false,
  db: this.ctx.db,
  enable: true,
  get: async (_key?: string) => { return null; },
  mget: async (_keys: string[]) => { return []; },
});
名称类型说明
ttlnumber缓存的过期时间
broadcastOnSetboolean | 'del'当设置缓存时,是否需要通过广播设置其他Workers的缓存。设置为del,那么就通过广播删除其他Workers的缓存
updateAgeOnGetboolean当读取缓存时是否更新ttl
ignoreNullboolean是否忽略null
mode'all' | 'mem' | 'redis'缓存模式
forceboolean强制读取新值
disableTransactionCompensateboolean是否禁止事务补偿
dbServiceDb在进行事务补偿时,会用到此db对象。在默认情况下,自动使用上下文中的db对象
enableboolean是否禁用Summer缓存
getFunction覆盖getNative方法
mgetFunction覆盖mgetNative方法
  • db: VonaJS 支持多数据库/多数据源,因此可以通过db精确控制事务补偿能力

缓存方法清单

名称说明
get读取缓存
mget同时读取多个缓存
peek拣取缓存,不更新缓存的ttl
set设置缓存
mset同时设置多个缓存
del删除缓存
mdel同时删除多个缓存
clear清理所有缓存

基于 MIT 许可发布