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

如何复用Redis连接并解决Rust中E0596可变借用编译错误

报错原因

你触发报错的核心是两个问题:

  1. as_ref()方法返回的是不可变引用&T,即使外层加&mut也无法将不可变引用转为可变引用,违反Rust的借用规则,而你的get_str方法显然需要传入可变的Redis连接引用。
  2. 你当前代码在缓存未命中分支调用redis_conn.unwrap()会直接消费掉redis_conn的所有权,即使第一个问题解决,也无法实现跨读写操作的连接复用。
修复方案

你只需要提前把get_con返回的Result解包,拿到可变的连接实例即可,全程只操作同一个可变引用,不需要重复调用as_ref、unwrap消费所有权:

修正后的完整代码如下:

#[get("/v1.1/playlist/detail/<req_playlist_id>")]
pub async fn playlist_detail_attr(req_playlist_id: i64, loginUserInfo: LoginUserInfo) -> content::Json<String> {
    let playlistKey = "music:playlist:";
    let keyResult = format!("{}{}", playlistKey, loginUserInfo.userId);
    const REDIS_CON_STRING: &str = "redis://AoGTmVy3U7@cruise-redis-master.reddwarf-cache.svc.cluster.local:6379";
    let redis_client = redis::Client::open(REDIS_CON_STRING).expect("can create redis client");
    // 提前解包Result拿到可变连接,全程复用这一个实例
    let mut redis_conn = get_con(redis_client).expect("redis connect failed");
    // 直接传可变引用即可,不需要调用as_ref
    let cached_playlist = get_str(&mut redis_conn, &keyResult).await;
    return if cached_playlist.as_ref().unwrap().is_empty() {
        let playlistDetail = query_playlist_detail(req_playlist_id).await;
        let res = ApiResponse {
            result: playlistDetail,
            ..Default::default()
        };
        let response_json = serde_json::to_string(&res).unwrap();
        // 直接传同一个连接的可变引用,不需要调用unwrap消费所有权
        set_str(&mut redis_conn, &keyResult, &response_json, 60*60*24*7);
        content::Json(response_json)
    } else {
        content::Json(cached_playlist.unwrap())
    }
}
连接复用优化建议

你当前代码每次请求都会新建Redis客户端和连接,高并发场景下性能会受影响,建议使用Redis连接池:

  • 可以选择deadpool-redis库,在服务启动时初始化连接池,存储到Web框架的全局状态中
  • 每次请求从连接池获取连接,使用完自动归还,不需要每次新建TCP连接,性能提升更明显

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 20:18:01