如何复用Redis连接并解决Rust中E0596可变借用编译错误
报错原因
你触发报错的核心是两个问题:
as_ref()方法返回的是不可变引用&T,即使外层加&mut也无法将不可变引用转为可变引用,违反Rust的借用规则,而你的get_str方法显然需要传入可变的Redis连接引用。- 你当前代码在缓存未命中分支调用
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
相关产品推荐
相关产品推荐

