redis 存储常见类型
1. 字符串(Strings)
Redis中的字符串是一个基本的数据类型,用于存储和检索字符串值。
-
用例:适合存储文本或数字,例如用户的姓名、电子邮件地址或者页面计数器。字符串类型也可以存储二进制数据,因此可以用来保存图片或序列化的对象。
-
优势:操作简单,能够进行原子操作,如递增(INCR)。
rust// 保存字符串 let _: () = conn.set("username", "alice").await.unwrap(); // 获取字符串 let username: String = conn.get("username").await.unwrap();
2. 列表(Lists)
Redis列表是字符串的集合,按插入顺序排序。
-
用例:适合用于实现消息队列、活动日志、最近访问的项目列表等。列表支持在两端添加或移除元素,可以作为栈或队列使用。
-
优势:提供快速的插入和删除操作。可以用作先进先出(FIFO)队列或后进先出(LIFO)堆栈。
rust// 向列表头部添加元素 let _: () = conn.lpush("events", "login").await.unwrap(); let _: () = conn.lpush("events", "logout").await.unwrap(); // 获取列表元素 let events: Vec<String> = conn.lrange("events", 0, -1).await.unwrap();
3. 集合(Sets)
集合是唯一字符串的无序集合。
-
用例:用于存储没有特定顺序的唯一元素,例如标签、访问的IP地址或者社交网络中的好友列表。
-
优势:能够快速地添加、删除和检查元素的存在,还可以执行集合间的操作,如并集、交集和差集。
rust// 向集合添加元素 let _: () = conn.sadd("tags", "redis").await.unwrap(); let _: () = conn.sadd("tags", "database").await.unwrap(); // 获取所有集合成员 let tags: Vec<String> = conn.smembers("tags").await.unwrap();
4. 有序集合(Sorted Sets)
有序集合类似于集合,但每个成员都有一个与之关联的分数。
-
用例:适合用于需要按分数排序的数据,如排行榜、优先队列或存储具有排序权重的数据。
-
优势:除了集合的基本操作外,还可以根据分数或字典顺序检索元素,以及获取特定范围内的元素。
rust// 向有序集合添加元素 let _: () = conn.zadd("leaderboard", "alice", 100).await.unwrap(); let _: () = conn.zadd("leaderboard", "bob", 200).await.unwrap(); // 获取有序集合元素 let leaderboard: Vec<(String, f64)> = conn.zrange_withscores("leaderboard", 0, -1).await.unwrap();
5. 散列(Hashes)
散列是键值对的集合,类似于编程语言中的字典或对象。
-
用例:用于存储对象或多个相关数据点,如用户的多个属性(姓名、年龄、电子邮件等)。
-
优势:可以一次性读取或写入多个字段,对于表示对象或聚合多个数据点非常有效。
rust// 向散列添加键值对 let _: () = conn.hset("user:100", email", "[alice@example.com]()").await.unwrap(); // 获取散列的所有键值对 let user_info: HashMap<String, String> =conn.hgetall("user:100").await.unwrap();
6. 位图(Bitmaps)
位图是一个以比特为单位的数组,每个比特位可以独立设置或查询。
-
用例:适合于需要标记存在或不存在的场景,如用户的签到情况、特定功能的开启关闭状态。
-
优势:空间效率极高,适合于处理大量的布尔值。
rust// 在位图中设置位 let _: () = conn.setbit("features", 0, true).await.unwrap(); // 启用功能0 // 从位图获取位值 let feature_enabled: bool = conn.getbit("features", 0).await.unwrap();
7. 超级日志(HyperLogLogs)
HyperLogLog是一种概率数据结构,用于高效地估计集合的基数(不同元素的数量)。
-
用例:适用于需要估计大量数据的唯一元素数量的场景,如网站的独立访客数。
-
优势:相对于传统的计数方法,HyperLogLog在内存使用上非常高效,特别是在处理大数据集时。
rust// 向HyperLogLog添加元素 let _: () = conn.pfadd("pageviews", "user1").await.unwrap(); let _: () = conn.pfadd("pageviews", "user2").await.unwrap(); // 获取近似基数 let unique_pageviews: i64 = conn.pfcount("pageviews").await.unwrap();
后端业务中选择合适的 Redis 数据类型以获得最佳的保存和查找效率,关键在于理解你的数据结构和使用场景。以下是一些常见的后端场景及推荐的 Redis 数据类型:
类型选择
1. 用户会话(User Sessions)
-
推荐类型:散列(Hash)
-
原因:散列可以存储用户会话对象的多个属性(如用户ID、令牌、最后访问时间等),并允许单独更新或检索特定字段。
rustlet _: () = conn.hset("session:userid", "token", "abc123").await.unwrap(); let _: () = conn.hset("session:userid", "last_access", "2023-01-01").await.unwrap();
2. 实时消息或事件队列(Real-time Messaging or Event Queuing)
-
推荐类型:列表(List)
-
原因:列表提供先进先出队列的特性,适合实时消息传递或任务队列。
rustlet _: () = conn.rpush("events_queue", "event1").await.unwrap(); let event: String = conn.lpop("events_queue").await.unwrap();
3. 访问计数器或频率限制(Access Counters or Rate Limiting)
-
推荐类型:字符串(String)
-
原因:字符串类型支持原子递增操作,适合用作计数器。
rustlet _: () = conn.incr("page_view_count", 1).await.unwrap(); let count: i64 = conn.get("page_view_count").await.unwrap();
4. 排行榜或分数排序(Leaderboards or Score Sorting)
-
推荐类型:有序集合(Sorted Set)
-
原因:有序集合根据分数自动排序,适合于排行榜等需要排序的数据。
-
Rust 示例:
rustlet _: () = conn.zadd("leaderboard", "user123", 2500).await.unwrap(); let leaderboard: Vec<(String, f64)> = conn.zrange_withscores("leaderboard", 0, -1).await.unwrap();
5. 唯一值集合(如标签或分类)(Unique Value Collections like Tags or Categories)
-
推荐类型:集合(Set)
-
原因:集合提供唯一值存储,适合于需要去重的场景。
-
Rust 示例:
rustlet _: () = conn.sadd("tags", "redis").await.unwrap(); let tags: Vec<String> = conn.smembers("tags").await.unwrap();
6. 多属性对象存储(Multi-attribute Object Storage)
-
推荐类型:散列(Hash)
-
原因:散列能够存储对象的多个字段,且可以独立地获取或更新这些字段。
rustlet _: () = conn.hset("user:100", "name", "Alice").await.unwrap(); let user: HashMap<String, String> = conn.hgetall("user:100").await.unwrap();
7. 功能标记或切换(Feature Flags or Toggles)
-
推荐类型:位图(Bitmap)
-
原因:位图适合存储布尔值,如功能的开启/关闭状态。
-
Rust 示例:
rustlet _: () = conn.setbit("features", 1, true).await.unwrap(); let feature_on: bool = conn.getbit("features", 1).await.unwrap();
选择合适的类型取决于你的具体需求。如果你的数据结构简单(比如单个的键值对),字符串可能就足够了。对于更复杂的数据结构,如用户资料或会话信息,散列可能更合适。如果你的应用涉及到排行榜或者需要排序的数据,