likes
comments
collection
share

Redis,常见存储类型以及在业务中如何选择

作者站长头像
站长
· 阅读数 13

redis 存储常见类型

1. 字符串(Strings)

Redis中的字符串是一个基本的数据类型,用于存储和检索字符串值。

  • 用例:适合存储文本或数字,例如用户的姓名、电子邮件地址或者页面计数器。字符串类型也可以存储二进制数据,因此可以用来保存图片或序列化的对象。

  • 优势:操作简单,能够进行原子操作,如递增(INCR)。

    // 保存字符串
    let _: () = conn.set("username", "alice").await.unwrap();
    
    // 获取字符串
    let username: String = conn.get("username").await.unwrap();
    

2. 列表(Lists)

Redis列表是字符串的集合,按插入顺序排序。

  • 用例:适合用于实现消息队列、活动日志、最近访问的项目列表等。列表支持在两端添加或移除元素,可以作为栈或队列使用。

  • 优势:提供快速的插入和删除操作。可以用作先进先出(FIFO)队列或后进先出(LIFO)堆栈。

    // 向列表头部添加元素
    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地址或者社交网络中的好友列表。

  • 优势:能够快速地添加、删除和检查元素的存在,还可以执行集合间的操作,如并集、交集和差集。

    // 向集合添加元素
    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)

有序集合类似于集合,但每个成员都有一个与之关联的分数。

  • 用例:适合用于需要按分数排序的数据,如排行榜、优先队列或存储具有排序权重的数据。

  • 优势:除了集合的基本操作外,还可以根据分数或字典顺序检索元素,以及获取特定范围内的元素。

    // 向有序集合添加元素
    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)

散列是键值对的集合,类似于编程语言中的字典或对象。

  • 用例:用于存储对象或多个相关数据点,如用户的多个属性(姓名、年龄、电子邮件等)。

  • 优势:可以一次性读取或写入多个字段,对于表示对象或聚合多个数据点非常有效。

    // 向散列添加键值对
    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)

位图是一个以比特为单位的数组,每个比特位可以独立设置或查询。

  • 用例:适合于需要标记存在或不存在的场景,如用户的签到情况、特定功能的开启关闭状态。

  • 优势:空间效率极高,适合于处理大量的布尔值。

    // 在位图中设置位
    let _: () = conn.setbit("features", 0, true).await.unwrap();  // 启用功能0
    
    // 从位图获取位值
    let feature_enabled: bool = conn.getbit("features", 0).await.unwrap();
    

7. 超级日志(HyperLogLogs)

HyperLogLog是一种概率数据结构,用于高效地估计集合的基数(不同元素的数量)。

  • 用例:适用于需要估计大量数据的唯一元素数量的场景,如网站的独立访客数。

  • 优势:相对于传统的计数方法,HyperLogLog在内存使用上非常高效,特别是在处理大数据集时。

    // 向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、令牌、最后访问时间等),并允许单独更新或检索特定字段。

    let _: () = 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)

  • 原因:列表提供先进先出队列的特性,适合实时消息传递或任务队列。

    let _: () = conn.rpush("events_queue", "event1").await.unwrap();
    let event: String = conn.lpop("events_queue").await.unwrap();
    

3. 访问计数器或频率限制(Access Counters or Rate Limiting)

  • 推荐类型:字符串(String)

  • 原因:字符串类型支持原子递增操作,适合用作计数器。

    let _: () = 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 示例

    let _: () = 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 示例

    let _: () = conn.sadd("tags", "redis").await.unwrap();
    let tags: Vec<String> = conn.smembers("tags").await.unwrap();
    

6. 多属性对象存储(Multi-attribute Object Storage)

  • 推荐类型:散列(Hash)

  • 原因:散列能够存储对象的多个字段,且可以独立地获取或更新这些字段。

    let _: () = 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 示例

    let _: () = conn.setbit("features", 1, true).await.unwrap();
    let feature_on: bool = conn.getbit("features", 1).await.unwrap();
    

选择合适的类型取决于你的具体需求。如果你的数据结构简单(比如单个的键值对),字符串可能就足够了。对于更复杂的数据结构,如用户资料或会话信息,散列可能更合适。如果你的应用涉及到排行榜或者需要排序的数据,from刘金,转载请注明原文链接。感谢!

转载自:https://juejin.cn/post/7323205509867159604
评论
请登录