mycommon_utils/database/
redis_util.rs

1use redis::{Client, Commands, FromRedisValue, RedisResult, ToRedisArgs};
2use std::num::NonZeroUsize;
3use r2d2::PooledConnection;
4use crate::error::{Error, Result};
5use crate::database::config::REDIS_POOL;
6
7/// Redis 工具类,封装了一些常用的 Redis 操作。
8
9pub struct RedisUtil {
10    connection: PooledConnection<Client>
11}
12
13impl RedisUtil {
14    /// 构造函数,初始化 Redis 客户端。
15    pub fn new() -> Result<RedisUtil> {
16        // 提取配置和连接池,若获取失败则直接返回错误
17        let client = REDIS_POOL.get().ok_or_else(|| {
18            tracing::error!("Failed to get Redis connection pool");
19            Error::NotFound()
20        })?;
21
22        // 获取连接,若失败则记录错误并返回错误
23        let connection = client.get().map_err(|e| {
24            tracing::error!("Failed to obtain Redis connection: {:?}", e);
25            Error::NotFound()
26        })?;
27
28        // 成功获取连接,创建并返回 RedisUtil 实例
29        Ok(RedisUtil {
30            connection
31        })
32    }
33
34    /// 同步设置 Redis 键值对。
35    pub fn set<T: ToRedisArgs>(&mut self, key: &str, value: &T) -> RedisResult<bool> {
36        let result = self.connection.set(key, value)?;
37        Ok(result)
38    }
39
40    /// 同步设置带有过期时间的 Redis 键值对。
41    pub fn set_with_expiry<T: ToRedisArgs>(&mut self, key: &str, value: &T, expiry_seconds: u64) -> RedisResult<()> {
42        let result =self.connection.set_ex(key, value, expiry_seconds)?;
43        Ok(result)
44    }
45
46    /// 同步为现有键设置过期时间。
47    pub fn expire(&mut self, key: &str, expiry_seconds: i64) -> RedisResult<bool> {
48        let result =self.connection.expire(key, expiry_seconds)?;
49        Ok(result)
50    }
51
52    /// 同步获取 Redis 键对应的值。
53    pub fn get<T: FromRedisValue>(&mut self,key: &str) -> RedisResult<Option<T>> {
54        let value: Option<T> = self.connection.get(key)?;
55        Ok(value)
56    }
57
58    /// 使用 Pipeline 进行批量操作(设置多个键值对)。
59    pub fn pipeline_operations<T: ToRedisArgs>(&mut self, keys: Vec<&str>, values: Vec<&T>) -> RedisResult<()> {
60        if keys.len() != values.len() {
61            return Err(redis::RedisError::from((
62                redis::ErrorKind::TypeError,
63                "Keys and values must have the same length",
64            )));
65        }
66        let mut pipe = redis::pipe();
67        for (key, value) in keys.iter().zip(values.iter()) {
68            pipe.set(*key, *value).ignore();
69        }
70        pipe.query::<()>(&mut self.connection)?;
71        Ok(())
72    }
73
74    /// 检查键是否存在。
75    /// 返回 true 表示键存在,false 表示键不存在。
76    pub fn exists(&mut self, key: &str) -> RedisResult<bool> {
77        let exists = self.connection.exists(key)?;
78        Ok(exists)
79    }
80
81    /// 删除一个或多个键。
82    /// 返回删除的键数量。
83    pub fn del_vec(&mut self, keys: Vec<&str>) -> RedisResult<usize> {
84        self.connection.del(keys)
85    }
86    /// 删除一个键。
87    /// 返回删除的键数量。
88    pub fn del(&mut self, key: &str) -> RedisResult<usize> {
89        self.connection.del(key)
90    }
91    /// 获取键的剩余生存时间(TTL),单位为秒。
92    pub fn ttl(&mut self, key: &str) -> RedisResult<isize> {
93        self.connection.ttl(key)
94    }
95
96    /// 对整数类型的键进行原子自增操作。
97    pub fn incr(&mut self, key: &str) -> RedisResult<isize> {
98        self.connection.incr(key, 1)
99    }
100
101    /// 对整数类型的键进行原子自减操作。
102    pub fn decr(&mut self, key: &str) -> RedisResult<isize> {
103        self.connection.decr(key, 1)
104    }
105
106    /// 设置哈希类型的键值对。
107    pub fn hset(&mut self, key: &str, field: &str, value: &str) -> RedisResult<()> {
108        self.connection.hset(key, field, value)
109    }
110
111    /// 获取哈希类型键的值。
112    pub fn hget(&mut self, key: &str, field: &str) -> RedisResult<Option<String>> {
113        self.connection.hget(key, field)
114    }
115
116    /// 向列表左侧推入元素。
117    pub fn lpush<T: FromRedisValue>(&mut self, key: &str, value: &str) -> RedisResult<T> {
118        self.connection.lpush(key, value)
119    }
120
121    /// 从列表右侧弹出元素。
122    pub fn rpop<T: ToString>(&mut self, key: &str, count: Option<usize>) -> RedisResult<Option<Vec<String>>> {
123        let non_zero_count = count.and_then(NonZeroUsize::new);
124        self.connection.rpop(key, non_zero_count)
125    }
126}
127
128// 使用示例:
129// let redis_util = Redis::new().unwrap();
130// redis_util.set("1", "aaa").unwrap();
131// println!("Set value to 'aaa'");