You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从消费端触发FusionCache的EagerRefresh主动刷新机制?

FusionCache EagerRefresh 触发方案(生产者-消费者场景)

针对你的场景——只有生产者服务能生成数据,需在缓存值进入宽限期时触发EagerRefresh,而消费者仍正常读取缓存(含宽限期旧值),以下是可行的解决方案:

方案1:直接读取FusionCache内置元数据

FusionCache会自动为每个缓存项存储元数据(过期时间、宽限期结束时间等),你无需解析内存/Redis的原始存储,直接通过GetMetadataAsync<T>方法获取:

// 生产者服务中的逻辑
var metadata = await _fusionCache.GetMetadataAsync<YourDataType>(cacheKey);

if (metadata != null)
{
    var now = DateTimeOffset.UtcNow;
    // 判断是否处于宽限期:当前时间 >= 缓存过期时间,且 < 过期时间+宽限期的绝对截止时间
    var isInGracePeriod = now >= metadata.ExpiresAt && now < metadata.AbsoluteExpiration;

    if (isInGracePeriod)
    {
        // 主动触发刷新:跳过现有缓存,直接生成新数据并更新缓存
        await _fusionCache.GetOrSetAsync(cacheKey, async () => await ProduceNewData(), options => options
            .SetDuration(TimeSpan.FromHours(1)) // 正常缓存时长
            .SetGracePeriod(TimeSpan.FromMinutes(10)) // 宽限期配置
            .SetEagerRefresh(true)
            .SkipCache(true) // 强制绕过缓存,生成新值覆盖
        );
    }
}

注意事项

  • GetMetadataAsync优先从本地内存缓存读取元数据,内存未命中时再从Redis背板获取,适配你的分布式缓存场景。
  • SkipCache(true)确保本次调用不会复用旧缓存值,直接生成最新数据并更新缓存。

方案2:调整EagerRefresh触发阈值,利用内置逻辑

FusionCache的EagerRefresh默认会在缓存剩余有效期低于阈值时,由第一个访问请求触发刷新。你可以让生产者定期调用缓存检查,配合调整触发阈值实现需求:

// 生产者的缓存配置
var cacheOptions = new FusionCacheEntryOptions()
    .SetDuration(TimeSpan.FromHours(1))
    .SetGracePeriod(TimeSpan.FromMinutes(10))
    .SetEagerRefresh(true)
    // 设置触发阈值:缓存剩余有效期小于15分钟时,触发EagerRefresh
    .SetEagerRefreshTriggerThreshold(TimeSpan.FromMinutes(15));

// 生产者通过定时任务(如Hangfire、HostedService)定期调用,触发刷新检查
await _fusionCache.TryGetAsync<YourDataType>(cacheKey, cacheOptions);

方案3:自定义元数据存储(备选)

若不想依赖FusionCache内置元数据,可在存储缓存时额外保存自定义元数据(单独Redis键或与数据序列化在一起):

// 存储数据时同步保存元数据
var data = await ProduceNewData();
var customMetadata = new CacheMetadata
{
    ExpiresAt = DateTimeOffset.UtcNow.AddHours(1),
    GracePeriodEndsAt = DateTimeOffset.UtcNow.AddHours(1).AddMinutes(10)
};

// 存储主数据到FusionCache
await _fusionCache.SetAsync(cacheKey, data, options => options
    .SetDuration(TimeSpan.FromHours(1))
    .SetGracePeriod(TimeSpan.FromMinutes(10))
);

// 存储自定义元数据到Redis(单独键)
await _redisConnection.GetDatabase().StringSetAsync($"{cacheKey}:metadata", JsonSerializer.Serialize(customMetadata));

然后在生产者中读取判断:

var metadataJson = await _redisConnection.GetDatabase().StringGetAsync($"{cacheKey}:metadata");
if (!metadataJson.IsNullOrEmpty)
{
    var customMetadata = JsonSerializer.Deserialize<CacheMetadata>(metadataJson);
    var now = DateTimeOffset.UtcNow;
    if (now >= customMetadata.ExpiresAt && now < customMetadata.GracePeriodEndsAt)
    {
        await RefreshCache(cacheKey); // 调用刷新逻辑
    }
}

// 刷新逻辑实现
async Task RefreshCache(string key)
{
    var newData = await ProduceNewData();
    await _fusionCache.SetAsync(key, newData, options => options
        .SetDuration(TimeSpan.FromHours(1))
        .SetGracePeriod(TimeSpan.FromMinutes(10))
        .SetEagerRefresh(true)
    );
}

内容的提问来源于stack exchange,提问作者ZorgoZ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 22:13:19