Redis的 散列(Hash) 和 列表(List) 数据结构操作详解
Redis 提供了丰富的数据结构操作命令,其中 散列(Hash) 和 列表(List) 是最常用的两种结构。以下分别详细介绍它们的常见操作、命令语法及应用场景,并附示例说明。
一、散列(Hash)操作
散列(Hash)是 Redis 中存储键值对集合的数据结构,适合表示"对象"的属性(如用户的姓名、年龄、邮箱等)。每个散列键对应一个字段(field)和值(value)的映射表,字段和值均为字符串类型。
1. 基础操作
(1)添加/修改字段(HSET)
-
命令 :
HSET key field value [field value ...]
-
作用 :向散列
key
中添加或修改一个或多个字段的值(若字段不存在则创建,存在则覆盖)。 -
返回值:成功添加的字段数量(整数)。
-
示例:
# 向用户对象(key=user:1001)中添加姓名和年龄 redis> HSET user:1001 name "Alice" age 28 (integer) 2 # 成功添加2个字段
(2)获取单个字段值(HGET)
-
命令 :
HGET key field
-
作用 :获取散列
key
中字段field
的值(若字段不存在返回nil
)。 -
示例:
redis> HGET user:1001 name "Alice" # 返回姓名字段的值
(3)批量获取多个字段值(HMGET)
-
命令 :
HMGET key field [field ...]
-
作用 :批量获取散列
key
中多个字段的值(不存在的字段返回nil
)。 -
示例:
redis> HMGET user:1001 name age email 1) "Alice" # name 字段的值 2) "28" # age 字段的值 3) (nil) # email 字段不存在,返回 nil
(4)获取散列所有字段和值(HGETALL)
-
命令 :
HGETALL key
-
作用 :获取散列
key
中所有字段(field)和对应的值(value),结果按field1, value1, field2, value2, ...
的顺序返回。 -
返回值:字段和值的列表(若散列为空则返回空列表)。
-
示例:
redis> HSET user:1001 email "alice@example.com" # 先添加 email 字段 (integer) 1 redis> HGETALL user:1001 1) "name" # 字段1 2) "Alice" # 值1 3) "age" # 字段2 4) "28" # 值2 5) "email" # 字段3 6) "alice@example.com" # 值3
(5)删除字段(HDEL)
-
命令 :
HDEL key field [field ...]
-
作用 :删除散列
key
中的一个或多个字段(返回成功删除的字段数量)。 -
示例:
redis> HDEL user:1001 age email # 删除 age 和 email 字段 (integer) 2 # 成功删除2个字段
(6)检查字段是否存在(HEXISTS)
-
命令 :
HEXISTS key field
-
作用 :检查散列
key
中是否存在字段field
(存在返回1
,不存在返回0
)。 -
示例:
redis> HEXISTS user:1001 name # name 字段存在 (integer) 1 redis> HEXISTS user:1001 age # age 字段已被删除 (integer) 0
(7)获取所有字段名(HKEYS)
-
命令 :
HKEYS key
-
作用 :获取散列
key
中所有字段名(返回列表,若散列为空则返回空列表)。 -
示例:
redis> HKEYS user:1001 1) "name" # 仅剩 name 字段
(8)获取所有字段值(HVALS)
-
命令 :
HVALS key
-
作用 :获取散列
key
中所有字段的值(返回列表,若散列为空则返回空列表)。 -
示例:
redis> HVALS user:1001 1) "Alice" # name 字段的值
(9)字段值自增(HINCRBY)
-
命令 :
HINCRBY key field increment
-
作用 :将散列
key
中字段field
的值(需为整数)增加increment
(若字段不存在则初始化为0
后再增加)。 -
返回值:增加后的值(整数)。
-
示例:
redis> HSET user:1001 login_count 5 # 初始化登录次数 (integer) 1 redis> HINCRBY user:1001 login_count 3 # 增加3次 (integer) 8 # 当前值为8
(10)获取散列长度(HLEN)
-
命令 :
HLEN key
-
作用 :获取散列
key
中字段的数量(返回整数,若散列不存在返回0
)。 -
示例:
redis> HLEN user:1001 (integer) 1 # 仅 name 字段
2. 散列的典型应用场景
-
对象存储 :如用户信息(
user:1001
对应姓名、年龄、手机号等字段)。 -
动态配置 :存储系统的动态参数(如
config:redis
对应max_memory
、timeout
等配置项)。 -
统计聚合 :按维度统计数据(如
stats:202408
对应pv
、uv
、order_count
等统计值)。
二、列表(List)操作
列表(List)是 Redis 中有序、可重复 的字符串集合,支持双向插入和删除(头部或尾部),底层通过快速列表(QuickList)实现,适合实现队列、栈、消息缓冲区等场景。
1. 基础操作
(1)从左侧插入元素(LPUSH)
-
命令 :
LPUSH key element [element ...]
-
作用 :将一个或多个元素插入到列表
key
的头部(左侧),返回插入后列表的长度。 -
示例:
redis> LPUSH mylist "a" "b" "c" # 从左插入 a、b、c (integer) 3 # 列表长度为3 redis> LRANGE mylist 0 -1 # 查看全部元素(0到末尾) 1) "c" # 插入顺序:a→b→c,头部插入后顺序变为 c→b→a 2) "b" 3) "a"
(2)从右侧插入元素(RPUSH)
-
命令 :
RPUSH key element [element ...]
-
作用 :将一个或多个元素插入到列表
key
的尾部(右侧),返回插入后列表的长度。 -
示例:
redis> RPUSH mylist "d" "e" # 从右插入 d、e (integer) 5 # 原长度3,插入后长度5 redis> LRANGE mylist 0 -1 1) "c" # 原列表:c→b→a 2) "b" 3) "a" 4) "d" # 新增 d→e(尾部插入) 5) "e"
(3)从左侧弹出元素(LPOP)
-
命令 :
LPOP key [count]
-
作用 :移除并返回列表
key
头部(左侧)的count
个元素(count
默认为1
,若列表为空返回nil
)。 -
示例:
redis> LPOP mylist 2 # 弹出左侧2个元素 1) "c" # 第一个弹出的元素 2) "b" # 第二个弹出的元素 redis> LRANGE mylist 0 -1 1) "a" # 剩余元素:a→d→e 2) "d" 3) "e"
(4)从右侧弹出元素(RPOP)
-
命令 :
RPOP key [count]
-
作用 :移除并返回列表
key
尾部(右侧)的count
个元素(count
默认为1
)。 -
示例:
redis> RPOP mylist 1 # 弹出右侧1个元素 "e" redis> LRANGE mylist 0 -1 1) "a" 2) "d" # 剩余元素:a→d
(5)获取指定范围的元素(LRANGE)
-
命令 :
LRANGE key start end
-
作用 :获取列表
key
中从索引start
到end
的元素(索引从0
开始,-1
表示最后一个元素)。 -
示例:
redis> LRANGE mylist 0 -1 # 获取全部元素 1) "a" 2) "d" redis> LRANGE mylist 0 0 # 获取第一个元素 1) "a" redis> LRANGE mylist -2 -1 # 获取最后两个元素(仅两个元素时即全部) 1) "a" 2) "d"
(6)获取列表长度(LLEN)
-
命令 :
LLEN key
-
作用 :返回列表
key
的长度(元素个数,若列表不存在返回0
)。 -
示例:
redis> LLEN mylist (integer) 2 # 当前列表有2个元素
(7)按索引获取元素(LINDEX)
-
命令 :
LINDEX key index
-
作用 :返回列表
key
中索引index
对应的元素(索引从0
开始,-1
表示最后一个元素)。 -
示例:
redis> LINDEX mylist 0 # 第一个元素 "a" redis> LINDEX mylist 1 # 第二个元素 "d" redis> LINDEX mylist -1 # 最后一个元素(等同于索引1) "d"
(8)修改指定索引的元素(LSET)
-
命令 :
LSET key index element
-
作用 :将列表
key
中索引index
对应的元素设置为element
(若索引超出范围则返回错误)。 -
示例:
redis> LSET mylist 1 "x" # 修改第二个元素为 x OK # 操作成功 redis> LRANGE mylist 0 -1 1) "a" 2) "x" # 原 d 被修改为 x
(9)截断列表(LTRIM)
-
命令 :
LTRIM key start end
-
作用 :保留列表
key
中索引start
到end
的元素,超出范围的元素被删除。 -
示例:
redis> RPUSH mylist "y" "z" # 先扩展列表:a→x→y→z (integer) 4 redis> LTRIM mylist 1 2 # 保留索引1到2的元素(x→y) OK redis> LRANGE mylist 0 -1 1) "x" 2) "y" # 原 a(索引0)和 z(索引3)被删除
(10)阻塞式弹出(BLPOP/BRPOP)
-
命令 :
BLPOP key [key ...] timeout
或BRPOP key [key ...] timeout
-
作用 :阻塞等待列表
key
头部(BLPOP)或尾部(BRPOP)的元素出现,超时时间timeout
单位为秒(0
表示永久阻塞)。 -
返回值 :若超时返回
nil
;否则返回[key, element]
(弹出的列表键和元素)。 -
应用场景:实现简单的消息队列(生产者 RPUSH,消费者 BRPOP 阻塞等待)。
-
示例:
# 消费者端(阻塞等待列表 myqueue 有元素) redis> BRPOP myqueue 10 # 等待10秒 1) "myqueue" # 弹出的列表键 2) "task1" # 弹出的元素(假设此时有其他客户端 RPUSH 了 task1)
2. 列表的典型应用场景
-
消息队列 :生产者通过
RPUSH
写入消息,消费者通过LPOP
或BRPOP
读取消息(FIFO 队列)。 -
栈结构 :生产者通过
LPUSH
写入,消费者通过LPOP
读取(LIFO 栈)。 -
历史记录 :存储用户的操作历史(如最近10条搜索记录,通过
LTRIM
限制长度)。 -
任务池 :存储待处理的任务,多个消费者通过
BRPOP
并发获取任务。
三、总结
Redis 的散列(Hash)和列表(List)是两种核心数据结构,分别适用于不同的场景:
-
散列:适合存储对象的多个属性(如用户信息),支持高效的字段级增删改查。
-
列表:适合处理有序、可重复的数据序列(如队列、栈、消息缓冲区),支持双向操作和阻塞等待。
熟练掌握这些操作,能帮助开发者在实际项目中高效利用 Redis 优化性能(如减少数据库查询、缓存热点数据)或实现复杂功能(如消息队列、计数器)。