alibaba / jetcache

JetCache is a Java cache framework.
Apache License 2.0
5.03k stars 1.05k forks source link

针对目前的aop机制 @Cache 是否能添加一个条件强制刷新元数据配置? #836

Closed Jiiiiiin closed 9 months ago

Jiiiiiin commented 9 months ago

业务需求如下: 1.比如一个外部服务提供分页的场景 2.我们需要在用户查询(或者刷新)第一页的数据记录的时候,不走缓存(多级),这点 目前的 注解中的 condition 配置可以满足 ,但是我们还想进一步,在查询外部返回结果的时候初始化或强制更新缓存(多级) 3.而在非第一页查询的情况下我们都走缓存

但是目前测试只要表达式类似 pagenum==1 之后,整个流程框架就不在管理了,就算配置了 postCondition 希望做一个“取反”操作也不行,感觉 postCondition 被前置的condition “包”住了。

根据检索issue 目前的最简单方案应该是在外部控制层先调用一个空标记为 @CacheInvalidate 再调用标注为 @Cache的方法

不知道老师觉得这种场景是否可以在 @Cache 上直接支持一下?

areyouok commented 9 months ago

我没有太看懂。

但你应该试试基于Cache API来实现复杂的逻辑,不是什么功能都一定要用注解实现。

Jiiiiiin commented 9 months ago

这个是,但是就是第一个是“懒”,主要还是避免太多动作,想尽量简洁明了的实现,上面想说的是,“有一种根据条件来进行刷新” @Cache 所包裹的数据(可能是数据库、我们这边是三方系统返回的数据)

Jiiiiiin commented 9 months ago

这是目前改造之后的做法,有上层来控制上面所需的条件重刷:


  @Override
  public SecPagingResType<RecordRespListOdrDtlType> entry(@NonNull final RecordsQryType qryType) {

    // step
    if (qryType.isFirstPage()) {
      recordsInfraclI.clearCacheData(qryType);
    }

    // step
    final BaseSecOrgRecordCmplxOdrType<RecordRespListOdrDtlType> recordCmplxOdrType = recordsInfraclI.qryPayRecords(qryType);

    // step paging
    return SecPagingResType.newInstance(
        qryType.getPageNum(),
        qryType.getPageSize(),
        recordCmplxOdrType.getTotalCount(),
        recordCmplxOdrType.getOdrDetails()
    );
  }

  public static final String CACHE_NAME_FOR_PAYMENT_RECORDS_EXT_SVC_QRY_PAY_RECORDS = "PaymentRecordsExtSvc.qryPayRecords:";

  public static final String CACHE_BIZ_KEY_FOR_QRY_TYPE_MOBILE_PHONE = "#qryType.mobilePhone";

  @Cached(
      name = CACHE_NAME_FOR_PAYMENT_RECORDS_EXT_SVC_QRY_PAY_RECORDS,
      key = CACHE_BIZ_KEY_FOR_QRY_TYPE_MOBILE_PHONE,
      expire = 180,
      cacheType = CacheType.BOTH,
      localLimit = 2000,
      localExpire = 120
  )
  @CachePenetrationProtect
  @Override
  public BaseSecOrgRecordCmplxOdrType<RecordRespListOdrDtlType> qryPayRecords(@NonNull final RecordsQryType qryType) {
    final RecordsQryPkg qryPkg = RecordsQryPkg.newInstance(qryType);
    final RecordsQryResPkg resPkg = this.recordsQryResPkgImbTransportClient.execute(qryPkg);
    logger.info("qryPayRecords do qry end");
    return resPkg.getSecOrgRecordCmplxOdrType();
  }

  @CacheInvalidate(
      name = CACHE_NAME_FOR_PAYMENT_RECORDS_EXT_SVC_QRY_PAY_RECORDS,
      key = CACHE_BIZ_KEY_FOR_QRY_TYPE_MOBILE_PHONE
  )
  @Override
  public void clearCacheData(@NonNull final RecordsQryType qryType) {}
areyouok commented 9 months ago

框架不会实现所有的需求,除非

  1. 符合框架的定位
  2. 是普遍的需求
  3. 有合理的解决方案
Jiiiiiin commented 9 months ago

谢谢老师 另外多请教一下 如上实例,在触发 @CacheInvalidate 方法的时候 ,能否把其他服务实例(这里的服务指的是一个springboot应用,实例指的是不同的主机上面的应用进程)中的local级别缓存清理呢?老师,我看您在2.7.0.M1 版本的升级说明中说已经支持lettuce的通知实现跨实例的本地缓存失效机制?

Jiiiiiin commented 9 months ago

如果我提交一个 PR,“@CacheOrRefresh 搭配refCondition ”来实现上面的需求可以吗 老师

areyouok commented 9 months ago

谢谢老师 另外多请教一下 如上实例,在触发 @CacheInvalidate 方法的时候 ,能否把其他服务实例(这里的服务指的是一个springboot应用,实例指的是不同的主机上面的应用进程)中的local级别缓存清理呢?老师,我看您在2.7.0.M1 版本的升级说明中说已经支持lettuce的通知实现跨实例的本地缓存失效机制?

这个已经支持了

areyouok commented 9 months ago

如果我提交一个 PR,“@CacheOrRefresh 搭配refCondition ”来实现上面的需求可以吗 老师

这个需求很奇怪,我不想这么做。理由如上面的列出的 3 条

Jiiiiiin commented 9 months ago

收到 谢谢老师