Go 如何在结果到达时管理缓存服务器上的重复请求

Go 如何在结果到达时管理缓存服务器上的重复请求,go,caching,concurrency,redis,Go,Caching,Concurrency,Redis,在一个用go语言编写的要求很高的web服务的上下文中,我正在考虑缓存一些计算。为此,我考虑使用Redis 我的应用程序很容易接收到大量包含相同负载的请求,这会触发代价高昂的计算。所以缓存将奖励并允许计算一次 考虑以下从中提取的图 我使用这个数字是因为我认为它有助于说明问题。该图考虑了一般的两种情况:书籍在缓存中,或者这本书不在缓存中。然而,该图不考虑从数据库中检索图书和其他“获得同一本书”请求时的暂时情况。在这种情况下,我想暂时将重复的请求排队,直到检索到书籍为止。接下来,一旦书籍已经到达,排队

在一个用
go
语言编写的要求很高的web服务的上下文中,我正在考虑缓存一些计算。为此,我考虑使用Redis

我的应用程序很容易接收到大量包含相同负载的请求,这会触发代价高昂的计算。所以缓存将奖励并允许计算一次

考虑以下从中提取的图 我使用这个数字是因为我认为它有助于说明问题。该图考虑了一般的两种情况:书籍在缓存中,或者这本书不在缓存中。然而,该图不考虑从数据库中检索图书和其他“获得同一本书”请求时的暂时情况。在这种情况下,我想暂时将重复的请求排队,直到检索到书籍为止。接下来,一旦书籍已经到达,排队的请求将得到响应,结果将保留在缓存中,以便将来快速检索请求

因此,我的问题是如何实现这一要求。我正在考虑在服务器(存储库)上使用一种表来写入查询数据库(computing,ready)的状态,但这似乎有点复杂,因为我需要处理一些竞争条件


因此,我想知道是否有人知道这个模式,或者Redis本身是否以某种方式实现了它(我在咨询中没有找到它,但我怀疑使用Redis锁是可能的)

您可以按照所述进行设计。但有些事情很重要

使用唯一键

为每本书使用一个唯一的键,如果该书曾经被更改,该键也应该更改。此设计使您的步骤(6)在Redis中保存书本成为一个幂等运算(您可以多次使用相同的结果)。所以你可以用“得到同样的书”来避免任何比赛条件

幂等请求或异步消息

我想暂时将重复请求排队,直到检索到该书。接下来,一旦书籍已经到达,排队的请求将得到结果的回复

我不建议按照您的描述对请求进行排队。如果请求是缓存未命中,则让它从数据库中检索它-但将其设计为幂等。或者,您应该以异步方式处理所有请求,并使用消息队列(例如RabbitMQ或其他),但这种解决方案会增加复杂性

序列化请求

我的问题是,虽然第二次计算仍然没有得到结果,但可能会有太多重复的请求到达,并且由于我需要避免重复计算的成本。我需要找到一种方法,在第一个请求的结果到达时保留它们

听起来您希望将计算序列化,而不是同时进行,因为您希望避免两次进行相同的计算。要解决这个问题,您应该让请求初始化计算,例如,将输入放入队列,然后以串行顺序进行计算(但如果它们具有不同的密钥,则可能同时进行),最后通知客户机,或者如果客户机正在订阅更新(更好的解决方案)


Redis确实支持,但这取决于您对客户端的要求。为了可扩展性,我推荐一种不带锁的解决方案。

您可以按照描述进行设计。但有些事情很重要

使用唯一键

为每本书使用一个唯一的键,如果该书曾经被更改,该键也应该更改。此设计使您的步骤(6)在Redis中保存书本成为一个幂等运算(您可以多次使用相同的结果)。所以你可以用“得到同样的书”来避免任何比赛条件

幂等请求或异步消息

我想暂时将重复请求排队,直到检索到该书。接下来,一旦书籍已经到达,排队的请求将得到结果的回复

我不建议按照您的描述对请求进行排队。如果请求是缓存未命中,则让它从数据库中检索它-但将其设计为幂等。或者,您应该以异步方式处理所有请求,并使用消息队列(例如RabbitMQ或其他),但这种解决方案会增加复杂性

序列化请求

我的问题是,虽然第二次计算仍然没有得到结果,但可能会有太多重复的请求到达,并且由于我需要避免重复计算的成本。我需要找到一种方法,在第一个请求的结果到达时保留它们

听起来您希望将计算序列化,而不是同时进行,因为您希望避免两次进行相同的计算。要解决这个问题,您应该让请求初始化计算,例如,将输入放入队列,然后以串行顺序进行计算(但如果它们具有不同的密钥,则可能同时进行),最后通知客户机,或者如果客户机正在订阅更新(更好的解决方案)


Redis确实支持,但这取决于您对客户端的要求。为了提高可扩展性,我建议使用不带锁的解决方案。

您是运行一个Go服务器实例还是运行多个Go服务器实例?如果是单个实例,那么一个纯Go解决方案可能是合适的。谢谢你的建议。目前,我正在运行一个,但仅仅出于扩展的原因,我应该准备运行几个。我同意w