在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庫

我要說說
網上賓友點評