在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,完整代碼可以在代碼庫中找到。

 

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

    63

  • 沒用

    5

  • 開心

    18

  • 憤怒

    4

  • 可憐

    22

1.如文章侵犯了您的版權,請發郵件通知本站,該文章將在24小時内刪除;
2.本站標注原創的文章,轉發時煩請注明來源;
3.交流群: 2702237 13835667

相關課文
  • rust編譯新的wasm項目操作流程(原文: 編譯 Rust 爲 WebAssembly)

  • axum框架當中獲取請求header, 和獲取header指定字段的方法

  • rust視圖模板庫askama的使用

  • 在M1 M2芯片的蘋果電腦上編譯intel x86的rust庫

我要說說
網上賓友點評