高 QPS 下 Golang+Redis 构建业务查询服务时,如何规避数据库穿透

109 阅读2分钟

问题:假设我们有一个数据查询服务,在高 QPS 场景下,如何设计一个基于 Golang 和 Redis 的方案来避免数据库穿透?要求在没有 Redis 缓存预热且数据库无法承受大量并发查询的情况下,保证每个请求都能获取到真实的道具数据,同时不使用布隆过滤器和限流措施。

为了应对查询量突然激增且之前没有 Redis 缓存的情况,避免大量请求穿透到数据库,可以采用以下思路设计 Go 语言服务:使用单例查询机制,即让大量并发请求中只有一个请求去查询数据库,其余请求等待该请求完成并获取相同结果。

下面是具体的实现代码:

代码解释

全局变量:

queryMutex:用于保护共享资源 querying 和 resultChan 的并发访问。

querying:一个映射,用于记录某个道具是否正在被查询。

resultChan:一个映射,用于存储每个道具查询结果的通道。

查询流程:

先从 Redis 中查询道具信息,如果存在则直接返回。

如果 Redis 中不存在,检查是否已有其他请求正在查询该道具。如果有,则等待该请求完成并获取结果。

如果没有其他请求正在查询,则开始本次查询。查询完成后,将结果存入 Redis,并通过通道将结果通知给其他等待的请求。

并发控制:

使用 sync.Mutex 确保同一时间只有一个请求去查询数据库。

使用通道 chan interface{} 让其他请求等待查询结果。

通过这种方式,可以避免大量并发请求同时穿透到数据库,确保数据库不会因为瞬间的高负载而崩溃。