面试题答案
一键面试1. 处理背压的策略及优缺点
- 丢弃策略:
- 优点:简单直接,当通道缓冲区满时,新的数据直接被丢弃。在某些对数据准确性要求不高,只关注最新数据的场景下很适用,例如实时监控系统,只需要最新的监控数据。
- 缺点:会丢失数据,不适合对数据完整性要求高的场景,比如金融交易数据处理。
- 缓冲策略:
- 优点:增加通道的缓冲区大小,使得接收端有更多时间来处理数据,减少数据丢失的可能性。适用于接收端处理速度有波动但总体能跟上发送端的场景。
- 缺点:如果缓冲区设置过大,会占用过多内存资源。而且如果接收端长时间处理不过来,缓冲区最终还是会满,导致数据丢失。
- 限流策略:
- 优点:发送端根据接收端的处理能力动态调整发送速度,保证数据不会积压,能有效避免背压问题。适用于对数据完整性要求高且接收端处理能力有限的场景。
- 缺点:实现相对复杂,需要额外的机制来协调发送端和接收端的速度。
2. 代码实现限流策略示例
use std::sync::Arc;
use tokio::sync::{mpsc, Semaphore};
#[tokio::main]
async fn main() {
// 创建一个信号量,用于限制发送速度
let semaphore = Arc::new(Semaphore::new(10));
let (mut sender, mut receiver) = mpsc::channel(100);
// 模拟发送端
tokio::spawn(async move {
for i in 0..1000 {
let permit = semaphore.clone().acquire().await.unwrap();
sender.send(i).await.unwrap();
drop(permit);
}
});
// 模拟接收端
tokio::spawn(async move {
while let Some(data) = receiver.recv().await {
println!("Received: {}", data);
// 模拟处理数据
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
}
});
// 等待一段时间,确保任务完成
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
}
在上述代码中,通过 Semaphore
实现了限流策略。发送端在发送数据前需要获取信号量的许可(这里设置最大并发数为10),从而限制了发送速度,避免接收端处理不过来导致背压。接收端则按正常逻辑接收并处理数据。