【从零开始的rust web开发之路 四】rust语言tokio异步使用redis教程

文章目录

前言

使用rust写web,自然是离不开redis缓存的。rust也有现成redis连接库,并且支持阻塞和异步两种模式。下面教程我我以tokio异步操作redis方式为主,同步的操作可以参考异步,区别不大

一、首先引入依赖

rust 复制代码
redis = { version = "0.24.0",features = [ "r2d2" , "tokio-comp" ] }

我这里feature开启了r2d2连接池,以及开启了tokio异步支持特性。

全部特性列表如下

可选功能

定义了一些可以启用其他功能的功能 如果需要的话。其中一些是默认打开的。

  • acl:启用 ACL 支持(默认启用)
  • aio:启用异步 IO 支持(默认启用)
  • geospatial:启用地理空间支持(默认启用)
  • script:启用脚本支持(默认启用)
  • r2d2:启用 R2D2 连接池支持(可选)
  • ahash:启用AHASH地图/设置支持并在内部使用AHASH(+7-10%性能)- (可选)
  • cluster:启用 Redis集群支持(可选)
  • cluster-async:启用异步 Redis 集群支持(可选)
  • tokio-comp:启用对 Tokio的支持(可选)
  • connection-manager:启用对自动重新连接的支持(可选)
  • keep-alive:通过板启用保持活动选项(可选)socket2

二、创建redis客户端

rust 复制代码
    let client = redis::Client::open("redis://127.0.0.1:6379/").unwrap();
    //获取连接
    let con = client.get_async_connection().await.expect("连接redis失败");

此处url的格式为redis://[][:@][:port][/]

db是redis数据库索引。可根据业务自行修改

三、相关操作

设置值

rust 复制代码
#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    con.set::<&str,u32,()>("my_key", 12).await.expect("操作失败");
}

此处<&str,u32,()>前两个泛型指定key,value。第三个泛型是实现了FromRedisValue Trait的返回,set方法可以不指定

mset设置多个key值

rust 复制代码
#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    con.mset::<&str,u32,()>(&[("my_key1", 100), ("my_key2", 200)]).await.expect("操作失败");
}

设置含有过期时间的值

rust 复制代码
#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    //设置60秒过期,第三个参数是过期时间
    con.pset_ex::<&str,u32,()>("my_key", 12,60*1000).await.expect("操作失败");
}

pset_ex是毫秒单位,set_ex是秒

如果key不存在才设置

rust 复制代码
#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    con.set_nx::<&str,u32,()>("key3",30).await.expect("操作失败");
}

获取基本类型值

rust 复制代码
#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    let value : u32 = con.get("my_key").await.expect("获取值失败");
    println!("my_key = {}", value);
}

删除一个键

rust 复制代码
#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    con.del::<&str, ()>("key3") .await.expect("删除redis key失败");
}

删除多个键

rust 复制代码
#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    // 多个键删除
    let keys_to_delete = vec!["my_key1", "my_key2"];
    let result = con.del::<&Vec<&str>, i32>(&keys_to_delete).await;
    match result {
        Ok(count) => println!("Deleted {} keys", count),
        Err(e) => println!("Error: {}", e),
    }
}

判断键是否存在

rust 复制代码
#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    // 判断键是否存在
    let exists : bool = con.exists("my_key").await.expect("执行redis命令失败");
    println!("exists: {}", exists);
}

更多详细的接口文档可以看官网AsyncCommands接口https://docs.rs/redis/0.24.0/redis/trait.AsyncCommands.html

如何使用json序列化

复制代码
 可以通过自定义方法添加泛型约束实现功能。使用serde_json库来进行序列化

导入相关依赖

rust 复制代码
[dependencies]
tokio = { version = "1.35.1", features = ["full"] }
redis = { version = "0.24.0",features = [ "r2d2" , "tokio-comp","json" ] }
serde_json = "1.0.111"
serde = { version = "1.0.195", features = ["derive"] }

代码相关实例

rust 复制代码
use redis::{aio, AsyncCommands, RedisError, RedisResult, ToRedisArgs};
use serde::{Deserialize, Serialize};
use serde::de::DeserializeOwned;

#[derive(Debug, Clone,Deserialize, Serialize)]
struct User{
    name: String,
    age: u8,
    email: String,
}

#[tokio::main]
async  fn main() {
    let client = redis::Client::open("redis://127.0.0.1:6379/10").unwrap();
    let mut con = client.get_async_connection().await.expect("连接redis失败");
    // 判断键是否存在
    let user = User{
        name: "zhangsan".to_string(),
        age: 18,
        email: "11111111".to_string(),
    };
    set_json(&mut con,"user1",&user).await.expect("设置失败");
    let user :User = get_json(&mut con, "user2").await.expect("获取失败,没有找到User");
    println!("user:{:?}",user);
}

//设置json格式对象
pub async fn set_json<K,T>(con: &mut aio::Connection, key: K, obj : &T) -> RedisResult<String>
    where K: ToRedisArgs + Send + Sync, T: Serialize{
    let json = serde_json::to_string(obj);
    match json {
        Ok(obj) => {
            con.set::<K,String, String>(key,obj).await
        },
        Err(e) => {return Err(RedisError::from(e));}
    }
}

//获得json格式对象
pub async fn get_json<K, T>(con: &mut aio::Connection, key: K) -> RedisResult<T>
    where K: ToRedisArgs + Send + Sync, T: DeserializeOwned{
    let json : String = con.get(key).await?;
    let result = serde_json::from_str(&json);
    return match result {
        Ok(obj) => { Ok(obj) },
        Err(e) => { Err(RedisError::from(e)) }
    }
}

通过这两个方法泛型约束据即可实现相关功能

总结

以上就是今天要讲的内容,本文介绍了rust语言tokio异步使用redis教程,后续会出一个扩展使用教程

相关推荐
uzong3 小时前
技术故障复盘模版
后端
GetcharZp4 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程4 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研4 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi5 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
阿华的代码王国6 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy6 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
鼠鼠我捏,要死了捏6 小时前
生产环境Redis缓存穿透与雪崩防护性能优化实战指南
redis·cache
AntBlack6 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt
bobz9657 小时前
pip install 已经不再安全
后端