前言

Redis作为高性能的键值对数据库,拥有丰富的命令集,这些命令是我们操作和管理Redis的基础。本文将系统地介绍Redis的常用命令,从基础操作到高级应用,帮助读者全面掌握Redis命令的使用技巧。

基本概念

Redis提供了200多个命令,这些命令可以按照数据类型和功能进行分类。在开始详细介绍前,我们需要了解几个基本概念:

  • 键(Key):Redis中的每个数据都有一个唯一的键
  • 值(Value):Redis支持多种数据类型作为值
  • TTL(Time To Live):键的生存时间
  • 原子性:Redis的命令操作都是原子性的

Redis命令分类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌───────────────────┐     ┌───────────────────┐     ┌───────────────────┐
│ │ │ │ │ │
│ 字符串命令 │ │ 列表命令 │ │ 哈希命令 │
│ │ │ │ │ │
└───────────────────┘ └───────────────────┘ └───────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ Redis命令集 │
│ │
└─────────────────────────────────────────────────────────────────────────┘
▲ ▲ ▲
│ │ │
┌───────────────────┐ ┌───────────────────┐ ┌───────────────────┐
│ │ │ │ │ │
│ 集合命令 │ │ 有序集合命令 │ │ 服务器管理命令 │
│ │ │ │ │ │
└───────────────────┘ └───────────────────┘ └───────────────────┘

连接与基础操作

连接到Redis服务器

1
2
3
4
5
6
7
8
9
10
11
# 基本连接
redis-cli

# 指定主机和端口
redis-cli -h 127.0.0.1 -p 6379

# 带密码连接
redis-cli -a password

# 指定数据库索引
redis-cli -n 1

基础键操作命令

命令 描述 示例
SET 设置键值 SET name “Redis”
GET 获取值 GET name
DEL 删除键 DEL name
EXISTS 检查键是否存在 EXISTS name
EXPIRE 设置过期时间(秒) EXPIRE name 10
TTL 查看剩余生存时间 TTL name
PERSIST 移除过期时间 PERSIST name
KEYS 查找键 KEYS *
RENAME 重命名键 RENAME oldkey newkey
TYPE 返回键的数据类型 TYPE name

示例操作:

1
2
3
4
5
6
7
8
9
10
11
12
> SET user:1:name "张三"
OK
> GET user:1:name
"张三"
> EXISTS user:1:name
(integer) 1
> TTL user:1:name
(integer) -1
> EXPIRE user:1:name 60
(integer) 1
> TTL user:1:name
(integer) 58

字符串命令

字符串是Redis最基本的数据类型,可以存储文本、序列化的对象或数字。

常用字符串命令

命令 描述 示例
SET 设置字符串值 SET key value
SETNX 仅键不存在时设置 SETNX key value
SETEX 设置值并指定过期时间 SETEX key seconds value
MSET 一次设置多个键值 MSET key1 value1 key2 value2
GET 获取字符串值 GET key
MGET 一次获取多个键值 MGET key1 key2
INCR 将整数值加1 INCR counter
INCRBY 将整数值增加指定数量 INCRBY counter 10
DECR 将整数值减1 DECR counter
DECRBY 将整数值减少指定数量 DECRBY counter 10
APPEND 追加字符串 APPEND key value
STRLEN 返回字符串长度 STRLEN key
GETRANGE 获取子字符串 GETRANGE key start end
SETRANGE 覆盖字符串的一部分 SETRANGE key offset value

示例操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> SET counter 10
OK
> INCR counter
(integer) 11
> INCRBY counter 5
(integer) 16
> DECR counter
(integer) 15
> GET counter
"15"
> APPEND greeting "Hello"
(integer) 5
> APPEND greeting " World"
(integer) 11
> GET greeting
"Hello World"
> STRLEN greeting
(integer) 11
> GETRANGE greeting 0 4
"Hello"

应用场景

字符串命令的主要应用场景:

  1. 缓存:存储常用数据
  2. 计数器:使用INCR系列命令
  3. 限速器:结合过期时间实现API限流
  4. 分布式锁:使用SETNX实现简单的分布式锁

哈希命令

哈希是字段-值对的集合,适合存储对象数据。

常用哈希命令

命令 描述 示例
HSET 设置哈希字段的值 HSET user:1 name “张三” age 25
HSETNX 仅当字段不存在时设置 HSETNX user:1 email “example@mail.com
HGET 获取哈希字段的值 HGET user:1 name
HMGET 获取多个哈希字段 HMGET user:1 name age
HGETALL 获取所有字段和值 HGETALL user:1
HDEL 删除一个或多个哈希字段 HDEL user:1 age
HEXISTS 检查字段是否存在 HEXISTS user:1 name
HKEYS 获取所有字段 HKEYS user:1
HVALS 获取所有值 HVALS user:1
HINCRBY 增加哈希字段的整数值 HINCRBY user:1 visits 1
HLEN 获取哈希字段数量 HLEN user:1

示例操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
> HSET user:1 name "张三" age 25 city "北京"
(integer) 3
> HGET user:1 name
"张三"
> HGETALL user:1
1) "name"
2) "张三"
3) "age"
4) "25"
5) "city"
6) "北京"
> HINCRBY user:1 age 1
(integer) 26
> HDEL user:1 city
(integer) 1
> HKEYS user:1
1) "name"
2) "age"

应用场景

哈希命令的主要应用场景:

  1. 用户信息存储:每个用户一个哈希表
  2. 配置信息:存储系统配置
  3. 购物车:每个用户的购物车商品信息
  4. 计数统计:如文章的阅读量、点赞数等

列表命令

列表是简单的字符串列表,按照插入顺序排序,可以从头部或尾部添加元素。

常用列表命令

命令 描述 示例
LPUSH 将元素添加到列表头部 LPUSH mylist value1 value2
RPUSH 将元素添加到列表尾部 RPUSH mylist value3 value4
LPOP 移除并返回列表头部元素 LPOP mylist
RPOP 移除并返回列表尾部元素 RPOP mylist
LLEN 获取列表长度 LLEN mylist
LRANGE 获取列表范围内的元素 LRANGE mylist 0 -1
LINDEX 通过索引获取列表元素 LINDEX mylist 0
LSET 通过索引设置列表元素 LSET mylist 0 “newvalue”
LREM 移除列表中的元素 LREM mylist 1 “value”
LTRIM 裁剪列表 LTRIM mylist 0 99
BLPOP 阻塞式弹出头部元素 BLPOP mylist 5
BRPOP 阻塞式弹出尾部元素 BRPOP mylist 5

示例操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
> LPUSH messages "消息3" "消息2" "消息1"
(integer) 3
> RPUSH messages "消息4" "消息5"
(integer) 5
> LRANGE messages 0 -1
1) "消息1"
2) "消息2"
3) "消息3"
4) "消息4"
5) "消息5"
> LPOP messages
"消息1"
> RPOP messages
"消息5"
> LLEN messages
(integer) 3
> LINDEX messages 0
"消息2"

应用场景

列表命令的主要应用场景:

  1. 消息队列:生产者LPUSH/RPUSH,消费者RPOP/LPOP
  2. 最新消息:如朋友圈最新动态、新闻列表
  3. 任务队列:使用BLPOP/BRPOP实现阻塞式任务队列
  4. 分页数据:使用LRANGE实现简单分页

集合命令

集合是无序的字符串集合,成员是唯一的。

常用集合命令

命令 描述 示例
SADD 向集合添加一个或多个成员 SADD myset member1 member2
SREM 移除集合中一个或多个成员 SREM myset member1
SMEMBERS 返回集合中所有成员 SMEMBERS myset
SISMEMBER 判断成员是否在集合中 SISMEMBER myset member1
SCARD 获取集合成员数 SCARD myset
SINTER 返回多个集合的交集 SINTER set1 set2
SUNION 返回多个集合的并集 SUNION set1 set2
SDIFF 返回多个集合的差集 SDIFF set1 set2
SRANDMEMBER 返回集合中的随机元素 SRANDMEMBER myset 2
SPOP 移除并返回集合中的随机元素 SPOP myset

示例操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> SADD team:a "张三" "李四" "王五" "赵六"
(integer) 4
> SADD team:b "张三" "钱七" "孙八"
(integer) 3
> SMEMBERS team:a
1) "张三"
2) "李四"
3) "王五"
4) "赵六"
> SINTER team:a team:b
1) "张三"
> SUNION team:a team:b
1) "张三"
2) "李四"
3) "王五"
4) "赵六"
5) "钱七"
6) "孙八"
> SISMEMBER team:a "李四"
(integer) 1
> SCARD team:a
(integer) 4

应用场景

集合命令的主要应用场景:

  1. 标签系统:为用户、文章等添加标签
  2. 唯一性检查:如邮箱地址、用户名等
  3. 共同好友:使用交集操作
  4. 随机抽奖:使用SRANDMEMBER或SPOP

有序集合命令

有序集合类似于集合,但每个成员关联一个分数,用于排序。

常用有序集合命令

命令 描述 示例
ZADD 添加成员和分数 ZADD scoreboard 89 “张三” 96 “李四”
ZREM 移除成员 ZREM scoreboard “张三”
ZRANGE 按索引范围获取成员 ZRANGE scoreboard 0 -1
ZREVRANGE 反向获取成员 ZREVRANGE scoreboard 0 -1
ZRANK 获取成员排名 ZRANK scoreboard “李四”
ZREVRANK 获取成员反向排名 ZREVRANK scoreboard “李四”
ZSCORE 获取成员分数 ZSCORE scoreboard “李四”
ZINCRBY 增加成员分数 ZINCRBY scoreboard 5 “张三”
ZCOUNT 统计分数范围内的成员数 ZCOUNT scoreboard 80 100
ZRANGEBYSCORE 获取指定分数范围的成员 ZRANGEBYSCORE scoreboard 80 100
ZREMRANGEBYSCORE 移除指定分数范围的成员 ZREMRANGEBYSCORE scoreboard 0 60

示例操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> ZADD leaderboard 1200 "玩家A" 1500 "玩家B" 1100 "玩家C" 2000 "玩家D"
(integer) 4
> ZRANGE leaderboard 0 -1 WITHSCORES
1) "玩家C"
2) "1100"
3) "玩家A"
4) "1200"
5) "玩家B"
6) "1500"
7) "玩家D"
8) "2000"
> ZREVRANGE leaderboard 0 2 WITHSCORES
1) "玩家D"
2) "2000"
3) "玩家B"
4) "1500"
5) "玩家A"
6) "1200"
> ZINCRBY leaderboard 300 "玩家C"
"1400"
> ZRANK leaderboard "玩家C"
(integer) 2

应用场景

有序集合命令的主要应用场景:

  1. 排行榜:游戏分数、销售排名等
  2. 带权重的队列:优先级任务队列
  3. 延迟队列:使用时间戳作为分数
  4. 范围查询:如按成绩、价格区间查询

事务命令

Redis事务允许在单个步骤中执行一组命令。

常用事务命令

命令 描述 示例
MULTI 标记事务开始 MULTI
EXEC 执行事务内所有命令 EXEC
DISCARD 丢弃事务 DISCARD
WATCH 监视键的修改 WATCH key1 key2
UNWATCH 取消监视 UNWATCH

示例操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> MULTI
OK
> SET account:1:balance 500
QUEUED
> SET account:2:balance 1000
QUEUED
> EXEC
1) OK
2) OK

# 使用WATCH实现乐观锁
> WATCH account:1:balance
OK
> MULTI
OK
> INCRBY account:1:balance 100
QUEUED
> EXEC # 如果account:1:balance在WATCH后被其他客户端修改,EXEC将返回nil
1) (integer) 600

发布/订阅命令

Redis提供了发布/订阅功能,用于构建消息系统。

常用发布/订阅命令

命令 描述 示例
SUBSCRIBE 订阅一个或多个频道 SUBSCRIBE channel1 channel2
PSUBSCRIBE 订阅匹配模式的频道 PSUBSCRIBE channel*
PUBLISH 发送消息到频道 PUBLISH channel1 “message”
UNSUBSCRIBE 退订频道 UNSUBSCRIBE channel1
PUNSUBSCRIBE 退订模式频道 PUNSUBSCRIBE channel*
PUBSUB CHANNELS 列出活跃频道 PUBSUB CHANNELS

示例操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 客户端A
> SUBSCRIBE news
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "news"
3) (integer) 1

# 客户端B
> PUBLISH news "今天发布了新版本"
(integer) 1

# 客户端A将收到
1) "message"
2) "news"
3) "今天发布了新版本"

脚本命令

Redis支持Lua脚本,用于执行复杂的原子操作。

常用脚本命令

命令 描述 示例
EVAL 执行Lua脚本 EVAL script numkeys key [key …] arg [arg …]
EVALSHA 执行已缓存的脚本 EVALSHA sha1 numkeys key [key …] arg [arg …]
SCRIPT LOAD 加载脚本 SCRIPT LOAD script
SCRIPT EXISTS 检查脚本是否存在 SCRIPT EXISTS sha1 [sha1 …]
SCRIPT FLUSH 删除所有脚本 SCRIPT FLUSH
SCRIPT KILL 杀死正在执行的脚本 SCRIPT KILL

示例操作:

1
2
3
4
5
6
> EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey "Hello"
OK

# 原子递增并检查限流
> EVAL "local current = redis.call('INCR', KEYS[1]) if current > tonumber(ARGV[1]) then return 0 else return 1 end" 1 rate:limit:user:123 "10"
(integer) 1

连接和服务器命令

连接命令

命令 描述 示例
AUTH 验证密码 AUTH password
PING 测试连接 PING
ECHO 回显消息 ECHO message
SELECT 切换数据库 SELECT 1
QUIT 关闭连接 QUIT

服务器管理命令

命令 描述 示例
INFO 获取服务器信息 INFO
CONFIG GET 获取配置 CONFIG GET maxmemory
CONFIG SET 设置配置 CONFIG SET maxmemory 1GB
DBSIZE 返回当前数据库的键数量 DBSIZE
FLUSHDB 删除当前数据库所有键 FLUSHDB
FLUSHALL 删除所有数据库中的所有键 FLUSHALL
TIME 返回服务器时间 TIME
SLOWLOG 管理慢查询日志 SLOWLOG GET 10
CLIENT LIST 获取客户端连接列表 CLIENT LIST
MONITOR 实时监控Redis命令 MONITOR

高级应用

位图操作(Bitmap)

位图允许我们对字符串值的位进行操作,非常节省空间。

命令 描述 示例
SETBIT 设置位的值 SETBIT key offset value
GETBIT 获取位的值 GETBIT key offset
BITCOUNT 统计位值为1的数量 BITCOUNT key [start end]
BITOP 对多个位图进行位运算 BITOP AND destkey key [key …]
BITPOS 查找第一个指定值的位 BITPOS key bit [start] [end]

示例应用:用户签到记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 用户1在2021年第5天签到
> SETBIT user:1:sign:202102 5 1
(integer) 0

# 用户1在2021年第6天签到
> SETBIT user:1:sign:202102 6 1
(integer) 0

# 检查用户1是否在第5天签到
> GETBIT user:1:sign:202102 5
(integer) 1

# 获取用户1在2月份的签到次数
> BITCOUNT user:1:sign:202102
(integer) 2

HyperLogLog

HyperLogLog是用于基数统计的概率数据结构,占用空间极小。

命令 描述 示例
PFADD 添加元素 PFADD key element [element …]
PFCOUNT 获取基数估算值 PFCOUNT key [key …]
PFMERGE 合并多个HyperLogLog PFMERGE destkey sourcekey [sourcekey …]

示例应用:网站UV统计

1
2
3
4
5
6
7
8
9
# 添加用户访问记录
> PFADD page:visits:today user1 user2 user3
(integer) 1
> PFADD page:visits:today user1 user4
(integer) 1

# 获取今日UV
> PFCOUNT page:visits:today
(integer) 4

地理空间(GEO)

GEO命令用于存储和查询经纬度坐标。

命令 描述 示例
GEOADD 添加地理位置 GEOADD key longitude latitude member
GEOPOS 获取地理位置 GEOPOS key member [member …]
GEODIST 计算两点距离 GEODIST key member1 member2 [unit]
GEORADIUS 查找给定经纬度一定半径内的成员 GEORADIUS key longitude latitude radius unit

示例应用:附近的餐厅

1
2
3
4
5
6
7
8
9
10
11
12
13
# 添加餐厅位置
> GEOADD restaurants 116.39 39.91 "餐厅A" 116.40 39.90 "餐厅B" 116.38 39.92 "餐厅C"
(integer) 3

# 计算两个餐厅的距离(米)
> GEODIST restaurants "餐厅A" "餐厅B" m
"1544.1996"

# 查找某坐标5公里内的餐厅
> GEORADIUS restaurants 116.38 39.90 5 km
1) "餐厅B"
2) "餐厅A"
3) "餐厅C"

流(Stream)

Redis 5.0新增的数据类型,用于实现消息队列。

命令 描述 示例
XADD 添加消息 XADD key [MAXLEN ~count] ID field value [field value …]
XREAD 读取消息 XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key …] ID [ID …]
XRANGE 获取范围内的消息 XRANGE key start end [COUNT count]
XLEN 获取流的长度 XLEN key
XDEL 删除消息 XDEL key ID [ID …]
XGROUP 管理消费者组 XGROUP CREATE key groupname id-or-$
XREADGROUP 从消费者组读取 XREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key …] ID [ID …]
XACK 确认消息处理 XACK key group ID [ID …]

示例应用:日志收集系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 添加日志消息
> XADD logs * type "info" message "用户登录" user_id "123"
"1613023671654-0"

# 读取日志消息
> XREAD COUNT 10 STREAMS logs 0
1) 1) "logs"
2) 1) 1) "1613023671654-0"
2) 1) "type"
2) "info"
3) "message"
4) "用户登录"
5) "user_id"
6) "123"

# 创建消费者组
> XGROUP CREATE logs logprocessors $
OK

# 从组中读取消息
> XREADGROUP GROUP logprocessors worker1 COUNT 1 STREAMS logs >
1) 1) "logs"
2) 1) 1) "1613023671654-0"
2) 1) "type"
2) "info"
3) "message"
4) "用户登录"
5) "user_id"
6) "123"

# 确认消息处理
> XACK logs logprocessors 1613023671654-0
(integer) 1

实战:常见应用场景的命令组合

分布式锁实现

1
2
3
4
5
# 获取锁(带超时自动释放)
SET resource_name unique_value NX PX 10000

# 释放锁(使用Lua脚本保证原子性)
EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 resource_name unique_value

限流器实现

1
2
3
4
5
6
7
8
# 简单计数器限流(每分钟允许10次请求)
INCR rate:limit:user:123
EXPIRE rate:limit:user:123 60

# 滑动窗口限流
ZADD sliding:window:user:123 current_timestamp request_id
ZREMRANGEBYSCORE sliding:window:user:123 0 (current_timestamp - window_size)
ZCARD sliding:window:user:123

延迟队列实现

1
2
3
4
5
6
# 添加延迟任务(score为执行时间戳)
ZADD delayed:queue current_timestamp+delay task_data

# 获取到期任务
ZRANGEBYSCORE delayed:queue 0 current_timestamp LIMIT 0 1
ZREM delayed:queue task_id

排行榜实现

1
2
3
4
5
6
7
8
9
10
11
# 更新得分
ZADD leaderboard score player_id

# 获取前10名
ZREVRANGE leaderboard 0 9 WITHSCORES

# 获取玩家排名
ZREVRANK leaderboard player_id

# 获取指定玩家前后5名
ZREVRANGE leaderboard (ZREVRANK leaderboard player_id) - 5 (ZREVRANK leaderboard player_id) + 5 WITHSCORES

性能优化技巧

使用管道(Pipeline)减少网络开销

1
2
3
4
5
6
7
8
9
10
11
# 不使用管道
SET key1 value1
SET key2 value2
SET key3 value3

# 使用管道(在客户端实现)
PIPELINE
SET key1 value1
SET key2 value2
SET key3 value3
EXEC

使用Lua脚本保证原子性

1
2
# 计数器递增并获取值,同时设置过期时间
EVAL "redis.call('INCR', KEYS[1]); redis.call('EXPIRE', KEYS[1], ARGV[1]); return redis.call('GET', KEYS[1]);" 1 counter 60

合理使用批量命令

1
2
3
4
5
6
7
# 单个命令
GET key1
GET key2
GET key3

# 批量命令
MGET key1 key2 key3

避免使用昂贵的命令

  1. KEYS 命令在大型数据库上可能导致性能问题,使用 SCAN 代替
  2. SORT 命令在大数据集上开销大
  3. 长时间运行的Lua脚本可能阻塞Redis
  4. 大型集合上的交集、并集操作

总结

Redis命令丰富而强大,通过灵活组合这些命令,可以实现各种复杂的功能和应用场景。本文介绍了Redis的基础命令到高级应用,希望能帮助读者更好地理解和使用Redis。

在实际应用中,应根据业务场景选择合适的命令和数据结构,并遵循以下原则:

  1. 选择合适的数据结构:不同数据结构在不同场景下性能表现不同
  2. 使用批量操作:减少网络往返
  3. 避免大键值:拆分大键值,避免阻塞服务器
  4. 合理使用过期时间:避免无限制地增长内存
  5. 使用Lua脚本:保证操作的原子性和减少网络往返

当你熟练掌握Redis的各种命令后,可以更高效地利用Redis解决实际问题,构建高性能、可扩展的系统。

参考资料