从下游服务请求数据时的Golang回退缓存策略

mdfafbf1  于 5个月前  发布在  Go
关注(0)|答案(2)|浏览(55)

该函数向下游服务发送一个请求来获取一些数据,而主服务对Redis的依赖性很强。我想实现一个策略,在下游服务和Redis都出现故障的情况下,减少对主服务的影响。目前我的想法是,如果下游服务和Redis都出现以下情况,使用一个TTL时间更长的回退Redis缓存示例来减少对主服务的负面影响:

var SendDownstreamServiceTypeRequest = func(ctx context.Context, param1 int64) ([]ds.ServiceType, error) {
    var rsp *Response
    cachedResult, err := getCachedInfo(ctx, param1)
    if err == nil {
        logger.SetLoggerContext(ctx, "UsingCache", true)
        rsp = &Response{Data: cachedResult}
    } else {

        fallbackCachedResult, fallbackErr := getFallbackCachedInfo(ctx, param1)
        if fallbackErr == nil {
            logger.SetLoggerContext(ctx, "UsingFallbackCache", true)
            rsp = &Response{Data: fallbackCachedResult}
        } else {
            // ... request from downstream service
            // ... 
            // add response data from downstream service to primary cache and fallback cache
            errPrimaryCache := setCachedInfo(ctx, param1, rsp.Data)
            if errPrimaryCache != nil {
                logger.SetLoggerContext(ctx, "UsingCache", err.Error())
            }
            errFallbackCache := setFallbackCachedInfo(ctx, param1, rsp.Data)
            if errFallbackCache != nil {
                logger.SetLoggerContext(ctx, "UsingFallbackCache", err.Error())
            }
        }

    }
    var result ds.Response
    err = json.Unmarshal(rsp.Data, &result.Data)
    if err != nil {
        return nil, err
    }
    return result.Data, nil
}

字符串
有没有更好的后备缓存策略可以实现到主服务中,以增加更多的冗余?谢谢

gorkyyrv

gorkyyrv1#

一个后备Redis示例也可以,但我认为这会更昂贵,因为你必须维护另一个Redis示例,并支付托管它的费用。
一种替代方案是在服务本身上实现内存缓存;将数据存储在主服务的内存中。一些Go库可以轻松实现这一点,例如https://github.com/patrickmn/go-cachehttps://github.com/allegro/bigcache。因此,数据流将首先从示例的内存->缓存->数据库中检索。
在服务上使用内存缓存的一个缺点是,如果你有同一个服务的多个示例,因为你必须正确地同步它们之间的数据。所以你可能需要实现一个cron,它每隔X个时间间隔清理内存缓存,或者在发生事件时清理存储的数据。这可以通过使用异步消息来完成(例如NSQ、RabbitMQ、Kafka等)。
希望有帮助:)!

1u4esq0p

1u4esq0p2#

如果ttl持续时间较短,请首先分析它以设置其最佳值(监控至关重要)。
除此之外,您还可以使用本地缓存优先的方法。(如果你的数据太大),你只能使用https://redis.io/docs/manual/keyspace-notifications/存储data availability信息。你会看到x关键字会在Redis上通知你key expirations,和s关键字通知你关于set operations。你可以在不同的goroutine中监听这些事件,以检查Redis中的密钥是否过期(如果过期了,别忘了原子删除它)。如果它已经过期了,你可能不想调用Redis的后备缓存来执行不必要的io操作。因此,你可以先在你的本地做像isExist("param1", struct{}/*don't use bool for memory optimizations*/)这样的原子操作,如果它不存在,你可以把param1设置到该高速缓存。
顺便说一下,如果您存储的数据不是很大,您也可以考虑将其存储在本地,但同样,请首先监视它,以避免内存存储成本增加

相关问题