You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Rust从Redis查询指定前缀的所有键值对,避免多次请求

在Rust中高效批量获取Redis指定前缀的键值对

要避免大量网络请求,核心思路是用Redis的SCAN命令增量获取匹配前缀的键,再用MGET命令批量拉取对应值——这两个操作能把多次请求合并为少批量请求,同时避开KEYS命令在生产环境的阻塞问题。

1. 添加依赖

在Cargo.toml中引入Redis客户端库(同步/异步版本可选):

# 同步版本
redis = "0.23"

# 异步版本(基于Tokio)
redis = { version = "0.23", features = ["tokio-comp", "tokio-native-tls"] }

2. 同步实现示例

use redis::{Client, RedisResult, cmd};

fn get_keys_with_prefix(client: &Client, prefix: &str) -> RedisResult<Vec<String>> {
    let mut conn = client.get_connection()?;
    // SCAN迭代器自动处理游标,匹配指定前缀的键
    let keys: Vec<String> = redis::cmd("SCAN")
        .arg(0)
        .arg("MATCH")
        .arg(format!("{}*", prefix))
        .arg("COUNT")
        .arg(1000) // 每次扫描返回的近似数量,可根据实际调整
        .iter(&mut conn)
        .collect();
    Ok(keys)
}

fn get_batch_values(client: &Client, keys: &[String]) -> RedisResult<Vec<Option<String>>> {
    let mut conn = client.get_connection()?;
    // MGET批量获取所有键的值,一次请求完成
    cmd("MGET")
        .arg(keys)
        .query(&mut conn)
}

fn main() -> RedisResult<()> {
    let client = Client::open("redis://127.0.0.1:6379/")?;
    let prefix = "user:";
    
    let keys = get_keys_with_prefix(&client, prefix)?;
    if keys.is_empty() {
        println!("No keys found with prefix {}", prefix);
        return Ok(());
    }
    
    let values = get_batch_values(&client, &keys)?;
    
    // 匹配键值对输出
    for (key, value) in keys.into_iter().zip(values) {
        println!("{}: {:?}", key, value);
    }
    
    Ok(())
}

3. 异步实现示例(基于Tokio)

use redis::{Client, AsyncCommands, RedisResult};
use tokio;

#[tokio::main]
async fn main() -> RedisResult<()> {
    let client = Client::open("redis://127.0.0.1:6379/")?;
    let mut conn = client.get_async_connection().await?;
    let prefix = "user:";
    
    // 异步SCAN迭代获取键
    let mut keys = Vec::new();
    let mut cursor = 0;
    loop {
        let (new_cursor, batch_keys): (u64, Vec<String>) = conn.scan_match(cursor, format!("{}*", prefix))
            .count(1000)
            .await?;
        keys.extend(batch_keys);
        cursor = new_cursor;
        if cursor == 0 {
            break;
        }
    }
    
    if keys.is_empty() {
        println!("No keys found with prefix {}", prefix);
        return Ok(());
    }
    
    // 异步MGET批量获取值
    let values: Vec<Option<String>> = conn.mget(keys.clone()).await?;
    
    // 输出键值对
    for (key, value) in keys.into_iter().zip(values) {
        println!("{}: {:?}", key, value);
    }
    
    Ok(())
}

关键优化点

  • SCAN替代KEYS:SCAN是增量迭代,不会长时间阻塞Redis服务,适合生产环境;客户端库的迭代器会自动处理游标续接,无需手动管理。
  • MGET批量取值:把N次GET请求合并为1次MGET请求,大幅减少网络往返次数。
  • COUNT参数调整:根据Redis中键的数量调整COUNT值(比如1000或更高),减少SCAN的迭代次数,进一步降低请求量。

内容的提问来源于stack exchange,提问作者Bob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 07:47:27