这个妙不可言的处理数据库查询的技巧,可以说是挽救了Discord。
它帮助Discord存储并检索了数万亿条信息,而且在整个过程中,他们的数据库集群都保持运转良好。
这个妙法就叫做请求合并(Request Coalescing)。
它的作用如此关键,实在不容忽视。
但是,为什么这个技术如此出色呢?
如果多个用户同时请求同一条信息,为何不只在数据库中查询一次呢?
这正是请求合并技术可以帮我们做到的。
下面是后台发生的详细过程(参见下图):
✅第一个发出请求的用户会启动数据服务中的一个工作任务。
✅对同一数据的后续请求会检查这个工作任务是否存在,如果存在则订阅这个任务。
✅一旦初始的工作任务查询了数据库并获得结果,它就会同时将结果返回给所有的订阅者。
使用请求合并技术有许多优势:
[1] 可以更有效地利用数据库资源。
[2] 能处理更多的并发请求,而不会产生过热的数据库区域。
[3] 可以降低延迟时间。
但也必须承认,这个技术有一些限制:
[1] 实现起来可能相当复杂,因为需要实现公平的分布式读写锁。说到底,我们需要让多个读取器同时访问数据,同时也要防止写入数据时发生冲突。
[2] 尽管总体上的延迟可能会降低,但某些请求可能需要更多的时间。
使用这个技术,我们需要考虑一些重要问题:
✅ 请求合并与缓存有什么不同?
使用请求合并的话,只有一个请求者会实际去触发对存储组件的查询,其他的请求则只是订阅这个请求。而使用缓存的话,所有的请求都会命中缓存。
✅ 为什么不直接使用缓存就好?
请求合并并不是要取代缓存。
你甚至可以在一个缓存基础上添加请求合并。毕竟,它的重点是减少针对数据源的请求次数。
✅ 在Discord的案例中,这个技术是如何实施的?
Discord并未正式公开他们的实施细节,不过我在论坛上找到了一些相关信息。
每个工作任务都有自己的本地状态,它实际上就是一个储存了请求和等待回应的发送方列表的哈希地图。
每当有回应传入,他们就会从哈希地图中移除请求,并将结果反馈给所有的请求者。
一般来说,我们并不需要使用请求合并技术。但在某些规模较大的情况下,它其实可以挽救你的业务。
那么你对这种技术怎么看呢?
你认为它是有益的,还是可能会带来问题呢?