知识卡片
请求合并:防止缓存未命中时并发请求穿透到后端
内容
客户端在缓存(无论内存缓存还是数据库缓存)中都没有命中某个域名记录时,需要向HttpDNS API接口发起网络请求获取数据;如果同一时刻有多个业务请求都在等待同一个域名(比如同一个应用刚启动、多处代码同时访问同一个域名)的解析结果,而没有额外的协调机制,就会导致同时向HttpDNS API发起多个重复的网络请求——白白浪费网络资源,还可能给服务端造成不必要的压力。团队的解决办法是在真正发起API请求之前,先加入一个”正在请求”队列:一旦发现某个域名已经有请求正在路上,后续针对同一域名的并发调用就不再重复发起网络请求,而是直接丢弃或等待前一个请求的结果。这是缓存系统中一个通用的模式(有时也称请求合并或单飞),核心思路是:当缓存未命中触发的是一次代价较高的外部调用时,需要有一层机制去识别”是否已经有一个针对同一份数据的请求正在进行”,避免同一份缺失的数据被多个并发请求重复地去获取,从而把多次冗余的外部调用收敛为一次。
参考来源
- 位置:《高可用架构(第1卷)》第7章《安全与网络》"7.2 App域名劫持之DNS高可用——开源版HttpDNS方案详解"节,"7.2.3 代码结构"(源文件:_epub-src/OEBPS/Text/Chapter7_2_4.xhtml)
- 结论依据:原文说明"比如用户访问api.weibo.cn域名,该域名目前在数据库中没有缓存,在内存中也没有缓存。在同时有多个请求来获取该域名的IP的时候,由于没有缓存Cache需要请求API接口获取数据,将会导致同时开启多个网络线程请求数据。解决办法是在请求API接口前增加正在请求队列",直接支撑本卡片结论。
- 原始内容:在同时有多个请求来获取该域名的IP的时候,由于没有缓存Cache需要请求API接口获取数据,将会导致同时开启多个网络线程请求数据。解决办法是在请求API接口前增加正在请求队列。