文章目录
- 前言
- [一、 String(字符串)结构](#一、 String(字符串)结构)
-
- [1.1 字符串常用操作命令](#1.1 字符串常用操作命令)
- [1.2 原子加减操作](#1.2 原子加减操作)
- [1.3 核心应用场景](#1.3 核心应用场景)
- [二、 Hash(哈希)结构](#二、 Hash(哈希)结构)
-
- [2.1 Hash 常用操作命令](#2.1 Hash 常用操作命令)
- [2.2 核心应用场景](#2.2 核心应用场景)
- [2.3 Hash 结构的优缺点分析](#2.3 Hash 结构的优缺点分析)
- [三、 List(列表)类型](#三、 List(列表)类型)
-
- [3.1 List 常用操作命令](#3.1 List 常用操作命令)
- [3.2 经典数据结构组合模拟](#3.2 经典数据结构组合模拟)
- [3.3 核心应用场景](#3.3 核心应用场景)
- [3.4 关键注意点](#3.4 关键注意点)
- [四、 Set(集合)类型](#四、 Set(集合)类型)
-
- [4.1 Set 常用基础操作](#4.1 Set 常用基础操作)
- [4.2 Set 核心运算操作](#4.2 Set 核心运算操作)
- [4.3 核心应用场景](#4.3 核心应用场景)
- [五、 ZSet(有序集合)类型](#五、 ZSet(有序集合)类型)
-
- [5.1 ZSet 常用操作命令](#5.1 ZSet 常用操作命令)
- [5.2 ZSet 高级集合运算操作](#5.2 ZSet 高级集合运算操作)
- [5.3 核心应用场景:实时热搜排行榜](#5.3 核心应用场景:实时热搜排行榜)
- 结语
前言
在当今的高并发、高性能系统架构中,Redis 无疑是缓存与高并发组件里的中流砥柱。Redis 7 提供了非常丰富的数据结构,用于应对各种复杂的业务场景。本篇文章将带你深度剖析 Redis 最核心、最基础的五大传统数据结构:String(字符串) 、Hash(哈希) 、List(列表) 、Set(集合) 和 ZSet(有序集合),全面解析它们的常用命令与经典应用场景。
一、 String(字符串)结构
String 是 Redis 中最简单、最基础、也是最常用的键值对数据类型。它的底层结构支持存储文本字符串、二进制数据以及数值。
1.1 字符串常用操作命令
SET key value:存入一个字符串键值对。MSET key value [key value ...]:批量存储多个字符串键值对。SETNX key value:存入一个不存在的字符串键值对;如果该键在数据库中已经存在,则该操作不起任何作用并返回0。GET key:获取指定字符串键的值。MGET key [key ...]:批量获取多个字符串键的值。DEL key [key ...]:删除一个或多个指定的键。EXPIRE key seconds:设置一个键的过期时间(单位为秒);如果超过设定时间,该键会自动过期失效,在数据库中也将无法被访问。APPEND key value:在已有键值的末尾追加指定的字符串内容。
1.2 原子加减操作
INCR key:将 key 中存储的数字值原子加 1。DECR key:将 key 中存储的数字值原子减 1。INCRBY key increment:将 key 所存储的值加上指定的整数增量 increment。DECRBY key decrement:将 key所存储的值减去指定的整数减量 decrement。
1.3 核心应用场景
- 单值缓存 :通过基本的
SET key value或APPEND key value缓存一些全局变量、配置、或者基础 Token 数据。 - 对象缓存 :
- 整体 JSON 存取 :
SET user:1 '{"name": "roy", "balance":1888}'。 - 多属性分离存取 :通过
MSET user:1:name roy user:1:balance 1888批量管理对象字段,配合MGET user:1:name user:1:balance进行高效读取。
- 整体 JSON 存取 :
- 分布式锁 :
利用SETNX product:10001 true来竞争锁。若返回 1 代表获取锁成功,返回 0 则代表失败。业务执行完毕后通过DEL product:10001释放锁。在实际高并发业务中,推荐引入原子过期的组合命令:SET product:10001 true ex 10 nx,以防止因为程序异常终止引发死锁问题。
二、 Hash(哈希)结构
Hash 结构是一个键值对集合,它非常类似于 Java 中的 HashMap 或 Python 中的字典,其内部由 field 和 value 组成,非常适合用于存储结构化的对象。
2.1 Hash 常用操作命令
HSET key field value:存储一个哈希表 key 中的 field 键值对。HSETNX key field value:仅在哈希表 key 中不存在 field 时,才存储该 field 键值对。HMSET key field value [field value ...]:在一个哈希表 key 中同时存储多个 field-value 键值对。HGET key field:获取哈希表 key 中指定 field 对应的值。HMGET key field [field ...]:批量获取哈希表 key 中多个 field 对应的值。HDEL key field [field ...]:删除哈希表 key 中的一个或多个 field 键值。HLEN key:返回哈希表 key 中 field 的字段数量。HGETALL key:返回哈希表 key 中所有的内部键值对(包括 field 与 value)。HINCRBY key field increment:为哈希表 key 中指定的 field 字段的值加上整数增量 increment。
2.2 核心应用场景
- 对象缓存 :可以用
HSET user:1 name roy balance 1888来单独存储并更新用户的各个独立属性,利用HMGET user:1 name balance自由获取所需字段。也可以使用类似二维表的设计,将多个对象聚合存储在一个大 Hash 表里。 - 电商购物车 :
- 业务设计 :以
用户id为key,商品id为field,商品数量为value。 - 添加商品 :
HSET cart:1001 10088 1。 - 增加数量 :
HINCRBY cart:1001 10088 1。 - 商品总数 (购物车总件数):
HLEN cart:1001。 - 删除商品 :
HDEL cart:1001 10088。 - 获取购物车所有商品 :
HGETALL cart:1001。
- 业务设计 :以
2.3 Hash 结构的优缺点分析
- 优点 :
- 同类数据进行归类整合存储,极大地方便了数据的维护与管理。
- 相比 String 的多键操作,对 CPU 和内存的消耗更小。
- 相比于散落的 String 键,Hash 存储结构更加紧凑,更加节省空间。
- 缺点 :
- Redis 的过期功能(Expire)不能直接应用在单个
field上,只能作用于整个主key。 - 在 Redis 集群架构(Cluster)下,由于 Hash 只能驻留在单台机器,因而不适合大规模或极大数据量的堆积使用。
- Redis 的过期功能(Expire)不能直接应用在单个
三、 List(列表)类型
List 类似一个有序的数据链表,支持从左侧(头部)或右侧(尾部)插入或弹出元素,并且具备两套索引体系:正数索引从左往右(从 0 开始),负数索引从右往左(从 -1 开始)。
3.1 List 常用操作命令
LPUSH key value [value ...]:将一个或多个值 value 插入到列表 key 的表头(最左边)。RPUSH key value [value ...]:将一个或多个值 value 插入到列表 key 的表尾(最右边)。LPOP key:移除并返回列表 key 的头元素(最左侧元素)。RPOP key:移除并返回列表 key 的尾元素(最右侧元素)。LRANGE key start stop:返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。BLPOP key [key ...] timeout:从列表表头弹出一个元素;若列表中没有元素,则会阻塞等待 timeout 秒,如果设置 timeout 为 0,则会一直阻塞等待直到有新数据加入。BRPOP key [key ...] timeout:从列表表尾弹出一个元素;若列表中没有元素,则会阻塞等待 timeout 秒,如果设置 timeout 为 0,则会一直阻塞等待直到有新数据加入。
3.2 经典数据结构组合模拟
通过巧妙的命令组合,List 可以非常简单地模拟出传统计算机科学里的核心数据结构:
- Stack(栈) =
LPUSH+LPOP(先进后出) - Queue(队列) =
LPUSH+RPOP(先进先出) - Blocking MQ(阻塞队列) =
LPUSH+BRPOP(高并发阻塞式消息队列)
3.3 核心应用场景
- 内容聚合流展示:常常用于视频列表、长文章或签到列表的分页和按时间倒序拉取。
- 业务流转:如医院挂号、银行柜台排队机系统的底层任务排队,以及各种简化版的轻量级 MQ 异步通信架构。
3.4 关键注意点
- 大 Key 问题 :一个 List 的极限容量虽然高达 2 32 − 1 2^{32}-1 232−1 个元素(约40亿),但在实际企业应用开发中,应严格防范大 Key,避免单列表存储过多数据拖慢内存回收与持久化。
- 性能损耗 :List 的底层在 Redis 7 内部表现为一个双向链表,对两端(双端)的操作性能极高。但是,如果企图通过索引下标直接访问或操作列表中间某个节点的数据(如
LINDEX等),需要进行全表遍历,此时性能就会比较低。
四、 Set(集合)类型
Redis 的 Set 类型是一个无序的、不可重复的字符串集合。它除了支持基础的增删改查以外,还天生具备多集合之间的数学运算(交、并、差集)能力。
4.1 Set 常用基础操作
SADD key member [member ...]:往集合 key 中存入元素;如果元素已存在则会自动忽略,若 key 不存在则新建一个集合。SREM key member [member ...]:从集合 key 中删除一个或多个指定的元素。SMEMBERS key:获取集合 key 中的所有元素。SCARD key:获取集合 key 内部目前的元素总个数。SISMEMBER key member:判断 member 元素是否存在于集合 key 当中。SRANDMEMBER key [count]:从集合 key 中随机选出 count 个元素,但不会从原集合中将元素删除。SPOP key [count]:从集合 key 中随机抽选并弹出 count 个元素,被选中的元素会从原集合中被彻底移除。
4.2 Set 核心运算操作
SINTER key [key ...]:计算多个指定集合之间的交集运算。SINTERSTORE destination key [key ...]:计算交集结果,并将其持久化存入新集合 destination 中。SUNION key [key ...]:计算多个指定集合之间的并集运算。SUNIONSTORE destination key [key ...]:计算并集结果,并将其持久化存入新集合 destination 中。SDIFF key [key ...]:计算以第一个集合为主体的多个集合之间的差集运算。SDIFFSTORE destination key [key ...]:计算差集结果,并将其持久化存入新集合 destination 中。
4.3 核心应用场景
- 微信/平台抽奖小程序 :
- 点击"参与抽奖"将用户 ID 加进集合:
SADD key {userID}。 - 管理员查看所有参与抽奖的用户列表:
SMEMBERS key。 - 开奖时抽取 count 名中奖者:如果是允许重复中奖的不同奖项,可用
SRANDMEMBER key [count];若是不允许重复中奖的排他奖项,则采用SPOP key [count]。
- 点击"参与抽奖"将用户 ID 加进集合:
- 微信、微博点赞、收藏与标签 :
- 点赞文章:
SADD like:{消息ID} {用户ID}。 - 取消点赞:
SREM like:{消息ID} {用户ID}。 - 检查某个用户当前是否点过赞:
SISMEMBER like:{消息ID} {用户ID}。 - 获取该消息所有点赞过的用户清单:
SMEMBERS like:{消息ID}。 - 获取当前消息的总赞数:
SCARD like:{消息ID}。
- 点赞文章:
- 社交关系链计算(交/并/差集应用) :
- 共同关注的人 :通过
SINTER set1 set2 set3完美找出多用户的重合交集。 - 朋友圈/人脉圈的总和 :通过
SUNION set1 set2聚合出所有好友的并集。 - 你可能认识的人(好友推荐) :通过
SDIFF set1 set2计算出两用户好友列表的社交差集,精准推荐潜在好友。
- 共同关注的人 :通过
五、 ZSet(有序集合)类型
ZSet(Sorted Set)是 Redis 极其精妙的一个高级数据类型。它保留了 Set 集合不能重复的特性,但集合内的每个元素都必须关联一个浮点数分值(score)。Redis 内部会根据这个分值,自动将集合内的元素进行从小到大的有序排列。
5.1 ZSet 常用操作命令
ZADD key score member [[score member] ...]:往有序集合 key 中加入带有一个或多个分值的元素。ZREM key member [member ...]:从有序集合 key 中删除指定的 member 元素。ZSCORE key member:返回有序集合 key 中指定元素 member 关联的当前分值。ZINCRBY key increment member:为有序集合 key 中指定的 member 元素的分值加上对应的增量 increment(可以为整数或浮点数)。ZCARD key:返回有序集合 key 内部所包含的总体元素总个数。ZRANGE key start stop [WITHSCORES]:按照分值从小到大 的正序排列方式,获取有序集合 key 中下标从 start 到 stop 区间内的元素(带WITHSCORES选项会一并返回其分值)。ZREVRANGE key start stop [WITHSCORES]:按照分值从大到小的倒序排列方式,获取有序集合 key 中下标从 start 到 stop 区间内的元素(排行榜的核心命令)。
5.2 ZSet 高级集合运算操作
ZUNIONSTORE destkey numkeys key [key ...]:计算多个指定有序集合之间的并集,并将得分求和/按配置计算后存入全新的有序集合 destkey 中。ZINTERSTORE destkey numkeys key [key ...]:计算多个指定有序集合之间的交集,并将重合元素的得分存入全新的有序集合 destkey 中。
5.3 核心应用场景:实时热搜排行榜
ZSet 最经典的杀手级应用场景非"实时热度排行榜"莫属。以下是完整的业务逻辑流转闭环模型:
-
热度/点击量实时递增 :
当某条新闻(如 "守护香港")被用户点击或搜索时,其热度权重自增 1:
bashZINCRBY hotNews:20190819 1 "守护香港" -
展示当日排行前十名的核心数据 :
在网站或 App 首页,需要展示当天热度最高的前 10 名(索引 0 到 9),按热度从大到小倒序输出:
bashZREVRANGE hotNews:20190819 0 9 WITHSCORES -
跨时间维度的多日(七日)搜索榜单综合计算 :
如果需要统计过去一整周(7天)的总排行,可利用并集计算,将 7 天的有序集合数据全部汇聚聚合到一个新集合中:
bashZUNIONSTORE hotNews:20190813-20190819 7 hotNews:20190813 hotNews:20190814 hotNews:20190815 hotNews:20190816 hotNews:20190817 hotNews:20190818 hotNews:20190819 -
完美展示这七日综合热度排行前十的数据结果 :
直接对刚刚汇聚而成的七日总集合进行倒序拉取,即可直观呈现周榜单:
bashZREVRANGE hotNews:20190813-20190819 0 9 WITHSCORES
结语
Redis五大基础数据类型各有其独特的结构优势与适用边界。精准选择String、Hash、List、Set或ZSet,并规避大Key与集群限制等陷阱,是构建高性能缓存架构的核心能力。