在rust/axum框架中操作redis

字号+ 编辑: 种花家 修订: 种花家 来源: 2023-09-18 我要说两句(0)

目前官方没有axum操作redis的demo, 一些代码案例又不符合国人的编写习惯。故而放个文章在这里。

通过 redis-rs 这个 crate,可以很方便的操作 redis。它提供了同步和异步两种连接,由于我们要集成到 axum 中,所以这里使用异步连接。本章将展示如何获取 redis 异步连接、如何将字符串保存到 redis、如何获取到保存在 redis 里的字符串以及如何通过 redis 保存和读取自定义结构体。

获取 redis 异步连接

redis 默认端口是 6379,由于作者使用 docker 运行了多个 redis 实例,所以示例代码中可能不是redis默认端口。请根据你自身的环境将连接字符串中的主机和端口等信息进行修改。

通过 redis::Client::open()方法可以建立与 redis 服务器的连接,然后使用get_async_connection()方法获取到异步连接。

let client = Client::open("redis://127.0.0.1:16379/").unwrap(); let conn = client
  .get_async_connection()
  .await
  .unwrap();

其中的连接字符串(open()函数的参数)有以下几种写法(中括号内的为可选参数,尖括号内的为必填参数):

redis://[<用户名>][:<密码>@]<主机名>[:端口][/数据库]

unix:///<路径>[?db=<数据库>][&pass=<密码>][&user=<用户名>]

redis+unix:///<路径>[?db=<数据库>][&pass=<密码>][&user=<用户名>]

假如url的方式没有用户名怎么办? 

redis的默认用户名就是default, 也可以用如下写法, 直接不写用户名, 用个冒号隔开就算完事:

redis://:{密码}@{主机名}:{端口}/数据库

假如密码里含有#之类的特殊字符怎么办? 

自行百度用在线urlencode工具把密码转义一下再放进去。注意不要把冒号圈A之类的必要分隔符号给转义了, 不然你也连不上。

将字符串保存到 redis

调用异步连接的set()方法,可以将字符串保存到 redis:

conn.set("键名","值").await;

示例代码如下:

async fn set() -> Result<&'static str, String> {

    let client = Client::open(REDIS_DSN).map_err(|err| err.to_string());

    let mut conn = client
        .get_async_connection()
        .await
        .map_err(|err| err.to_string());
    conn.set("author", "axum.rs")
        .await
        .map_err(|err| err.to_string());

    Ok("Successfully set")
}

读取保存在 redis 中的字符串

异步连接的get()方法,用于从 redis 中获取指定键的数据:

let value = conn.get("键名").await;

示例代码如下:

use redis::{FromRedisValue, RedisResult};

async fn get() -> Result<String, String> {

    let client = Client::open(REDIS_DSN).map_err(|err| err.to_string())?;
    let mut conn = client
        .get_async_connection()
        .await
        .map_err(|err| err.to_string());

    let somevalue = redis::cmd("GET").arg("some").query_async(&mut conn).await.map_err(|err| err.to_string()).unwrap();

    // 判断数据类型, 同时起到了判断当前key是否存在的作用
    match &somevalue {
        redis::Value::Nil => println!("{}", String::new()), // 初始化空字符串代替redis的Nil
        some => {
            // redis数据类型转为rust可用类型
            let some1: String = FromRedisValue::from_redis_value(some).unwrap();
        },
    }
  
    Ok(somevalue)
}

由于 redis 保存的是自己搞的底层数据,你需要转化成rust可用的数据, 你得根据需要将读取到的数据进行类型转换,官方文档有个redis::FromRedisValue的trait可以用。链接在此:

https://docs.rs/redis/latest/redis/trait.FromRedisValue.html

自定义结构体和 redis

了解完字符串的读写操作,我们继续讨论在 redis 读写自定义结构体。

定义数据结构

#[derive(Serialize, Deserialize)]pub struct UserInfo { pub id: i32, pub username: String, pub email: String,
}

将自定义结构体写入 redis 服务器

我们需要将结构体序列化为字符串,然后再写入 redis 服务器:

async fn set_user() -> Result<&'static str, String> { let client = Client::open(REDIS_DSN).map_err(|err| err.to_string())?; let mut conn = client
  .get_async_connection()
  .await
  .map_err(|err| err.to_string())?; let user = UserInfo {
  id: 1,
  username: "axum.rs".to_string(),
  email: "team@axum.rs".to_string(),
 }; let user = json!(user);
 conn.set("user", user.to_string())
  .await
  .map_err(|err| err.to_string())?; Ok("Successfully set user.")
}

从 redis 中读取自定义结构体

我们需要将 redis 中读取到的字符串反序列化为自定义结构体:

async fn get_user() -> Result<Json<UserInfo>, String> { let client = Client::open(REDIS_DSN).map_err(|err| err.to_string())?; let mut conn = client
  .get_async_connection()
  .await
  .map_err(|err| err.to_string())?; let value: String = conn.get("user").await.map_err(|err| err.to_string())?; let user: UserInfo = from_str(&value).map_err(|err| err.to_string())?; Ok(Json(user))
}

设置自动过期

redis 支持在写入值的时候设置过期时间,时间一到,该数据自动删除:

conn.set_ex("键名","值",过期时间的秒数).await;

本章讨论了如何在 axum 集成 redis,完整代码可以在代码库中找到。

 

阅完此文,您的感想如何?
  • 有用

    62

  • 没用

    3

  • 开心

    17

  • 愤怒

    3

  • 可怜

    21

1.如文章侵犯了您的版权,请发邮件通知本站,该文章将在24小时内删除;
2.本站标注原创的文章,转发时烦请注明来源;
3.交流群: PHP+JS聊天群

相关课文
  • rust编译新的wasm项目操作流程(原文: 编译 Rust 为 WebAssembly)

  • axum框架当中获取请求header, 和获取header指定字段的方法

  • rust视图模板库askama的使用

  • 在M1 M2芯片的苹果电脑上编译intel x86的rust库

我要说说
网上宾友点评