08-27-周三_17-09-29
This commit is contained in:
590
数据库/Redis_2025/04_Redis基本命令.md
Normal file
590
数据库/Redis_2025/04_Redis基本命令.md
Normal file
@@ -0,0 +1,590 @@
|
||||
# Redis 基本命令
|
||||
|
||||
Redis 提供了丰富的命令来管理键、数据库、事务和脚本。掌握这些基本命令是高效使用 Redis 的基础。
|
||||
|
||||
## 键操作命令
|
||||
|
||||
### 键的命名规范
|
||||
|
||||
良好的键命名规范是 Redis 应用的重要基础,有助于提高可维护性和性能。
|
||||
|
||||
**推荐的命名规范:**
|
||||
|
||||
1. **使用冒号分隔层级**
|
||||
```shell
|
||||
user:1001:profile
|
||||
product:category:electronics
|
||||
cache:query:user_list
|
||||
session:web:abc123
|
||||
```
|
||||
|
||||
2. **使用有意义的前缀**
|
||||
```shell
|
||||
# 按功能分类
|
||||
cache:* # 缓存数据
|
||||
session:* # 会话数据
|
||||
config:* # 配置信息
|
||||
temp:* # 临时数据
|
||||
|
||||
# 按业务分类
|
||||
user:* # 用户相关
|
||||
order:* # 订单相关
|
||||
product:* # 商品相关
|
||||
```
|
||||
|
||||
3. **避免特殊字符**
|
||||
```shell
|
||||
# 推荐
|
||||
user:1001:name
|
||||
article:2023:01:15
|
||||
|
||||
# 不推荐
|
||||
user 1001 name
|
||||
article@2023#01#15
|
||||
```
|
||||
|
||||
4. **保持一致性**
|
||||
```shell
|
||||
# 统一使用小写
|
||||
user:profile:name
|
||||
user:profile:email
|
||||
|
||||
# 统一日期格式
|
||||
log:2024:01:15
|
||||
report:2024:01:15
|
||||
```
|
||||
|
||||
### 键的查询和遍历
|
||||
|
||||
**基本查询命令**
|
||||
|
||||
```shell
|
||||
# 检查键是否存在
|
||||
# 用法:EXISTS key [key ...]
|
||||
EXISTS user:1001
|
||||
EXISTS user:1001 user:1002 user:1003 # 返回存在的键数量
|
||||
|
||||
# 获取键的类型
|
||||
# 用法:TYPE key
|
||||
TYPE user:1001 # 返回 hash
|
||||
TYPE user:tags # 返回 set
|
||||
TYPE message_queue # 返回 list
|
||||
|
||||
# 获取键的编码方式
|
||||
# 用法:OBJECT ENCODING key
|
||||
OBJECT ENCODING user:1001
|
||||
OBJECT ENCODING counter
|
||||
|
||||
# 获取键的空闲时间(秒)
|
||||
# 用法:OBJECT IDLETIME key
|
||||
# 注意:返回值为键的空闲时间,单位为秒。
|
||||
OBJECT IDLETIME user:1001
|
||||
|
||||
# 获取键的引用计数
|
||||
# 用法:OBJECT REFCOUNT key
|
||||
# 注意:返回值为键的引用计数,单位为秒。
|
||||
OBJECT REFCOUNT user:1001
|
||||
```
|
||||
|
||||
**模式匹配查询**
|
||||
|
||||
```shell
|
||||
# 查找匹配模式的键(谨慎使用)
|
||||
# 用法:KEYS pattern
|
||||
KEYS user:* # 查找所有用户相关的键
|
||||
KEYS cache:* # 查找所有缓存键
|
||||
KEYS *:1001:* # 查找包含1001的键
|
||||
KEYS user:100? # ?匹配单个字符
|
||||
KEYS user:[12]* # []匹配字符集合
|
||||
|
||||
# 更安全的遍历方式(推荐)
|
||||
# 用法:SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
|
||||
SCAN 0 MATCH user:* COUNT 10
|
||||
SCAN 0 MATCH cache:* COUNT 20
|
||||
SCAN 0 TYPE string COUNT 10
|
||||
|
||||
# 示例:安全遍历所有用户键
|
||||
redis-cli --scan --pattern "user:*"
|
||||
```
|
||||
|
||||
**随机获取键**
|
||||
|
||||
```shell
|
||||
# 随机返回一个键
|
||||
# 用法:RANDOMKEY
|
||||
|
||||
# 示例:随机获取键进行采样
|
||||
RANDOMKEY
|
||||
RANDOMKEY
|
||||
RANDOMKEY
|
||||
```
|
||||
|
||||
### 键的过期设置
|
||||
|
||||
Redis 支持为键设置过期时间,这是内存管理和缓存实现的重要功能。
|
||||
|
||||
**设置过期时间**
|
||||
|
||||
```shell
|
||||
# 设置键的过期时间(秒)
|
||||
# 用法:EXPIRE key seconds
|
||||
EXPIRE user:1001 3600 # 1小时后过期
|
||||
EXPIRE temp_data 300 # 5分钟后过期
|
||||
|
||||
# 设置键的过期时间(毫秒)
|
||||
# 用法:PEXPIRE key milliseconds
|
||||
PEXPIRE temp_data 30000 # 30秒后过期
|
||||
|
||||
# 设置键的过期时间戳(秒)
|
||||
# 用法:EXPIREAT key timestamp
|
||||
EXPIREAT temp_data 1705123200 # 指定时间戳过期
|
||||
|
||||
# 设置键的过期时间戳(毫秒)
|
||||
# 用法:PEXPIREAT key milliseconds-timestamp
|
||||
PEXPIREAT temp_data 1705123200000
|
||||
|
||||
# 创建键时同时设置过期时间
|
||||
# 用法:SETEX key seconds value
|
||||
SETEX key seconds value
|
||||
SETEX session:abc123 3600 "user_data"
|
||||
|
||||
# 创建键时同时设置过期时间(毫秒)
|
||||
# 用法:PSETEX key milliseconds value
|
||||
PSETEX session:def456 3600000 "user_data"
|
||||
```
|
||||
|
||||
**查询过期时间**
|
||||
|
||||
```shell
|
||||
# 获取键的剩余生存时间(秒)
|
||||
# 用法:TTL key
|
||||
TTL session:abc123 # 返回剩余秒数,-1表示永不过期,-2表示不存在
|
||||
|
||||
# 获取键的剩余生存时间(毫秒)
|
||||
# 用法:PTTL key
|
||||
PTTL session:abc123 # 返回剩余毫秒数
|
||||
|
||||
# 示例:检查多个键的过期时间
|
||||
SETEX key1 100 "value1"
|
||||
SETEX key2 200 "value2"
|
||||
SET key3 "value3" # 永不过期
|
||||
TTL key1
|
||||
TTL key2
|
||||
TTL key3
|
||||
```
|
||||
|
||||
**移除过期时间**
|
||||
|
||||
```shell
|
||||
# 移除键的过期时间,使其永久存在
|
||||
# 用法:PERSIST key
|
||||
PERSIST session:abc123
|
||||
SETEX temp_key 300 "临时数据"
|
||||
TTL temp_key # 查看过期时间
|
||||
PERSIST temp_key # 移除过期时间
|
||||
TTL temp_key # 返回-1,表示永不过期
|
||||
```
|
||||
|
||||
### 键的删除和重命名
|
||||
|
||||
**删除键**
|
||||
|
||||
```shell
|
||||
# 删除一个或多个键
|
||||
# 用法:DEL key [key ...]
|
||||
DEL user:1001
|
||||
DEL cache:query1 cache:query2 cache:query3
|
||||
|
||||
# 异步删除键(适用于大键)
|
||||
# 用法:UNLINK key [key ...]
|
||||
UNLINK large_list large_set large_hash
|
||||
|
||||
# 删除所有键(危险操作)
|
||||
FLUSHDB # 删除当前数据库所有键
|
||||
FLUSHALL # 删除所有数据库所有键
|
||||
```
|
||||
|
||||
**重命名键**
|
||||
|
||||
```shell
|
||||
# 重命名键
|
||||
# 用法:RENAME key newkey
|
||||
RENAME user:1001 user:1002
|
||||
SET old_name "value"
|
||||
RENAME old_name new_name
|
||||
GET new_name
|
||||
|
||||
# 仅当新键不存在时重命名
|
||||
# 用法:RENAMENX key newkey
|
||||
RENAMENX source_key target_key # 成功返回1
|
||||
RENAMENX source_key target_key # 失败返回0(target_key已存在)
|
||||
```
|
||||
|
||||
## 数据库操作
|
||||
|
||||
### 多数据库概念
|
||||
|
||||
Redis 支持多个数据库,默认有16个数据库(编号0-15),可以通过配置文件修改数量。
|
||||
|
||||
**数据库特点:**
|
||||
- 每个数据库都是独立的键空间
|
||||
- 不同数据库间的键名可以相同
|
||||
- 默认连接到数据库0
|
||||
- 数据库间不支持关联查询
|
||||
|
||||
**使用场景:**
|
||||
- 区分不同环境(开发、测试、生产)
|
||||
- 分离不同类型的数据
|
||||
- 临时数据隔离
|
||||
|
||||
### 数据库切换
|
||||
|
||||
```shell
|
||||
# 切换到指定数据库
|
||||
# 用法:SELECT index
|
||||
SELECT 0 # 切换到数据库0
|
||||
SELECT 1 # 切换到数据库1
|
||||
SELECT 15 # 切换到数据库15
|
||||
|
||||
# 示例:在不同数据库中存储数据
|
||||
SELECT 0
|
||||
SET app:env "production"
|
||||
SET app:version "1.0.0"
|
||||
|
||||
SELECT 1
|
||||
SET app:env "development"
|
||||
SET app:version "1.1.0-dev"
|
||||
|
||||
SELECT 2
|
||||
SET temp:data "临时测试数据"
|
||||
|
||||
# 验证数据隔离
|
||||
SELECT 0
|
||||
GET app:env # 返回 "production"
|
||||
|
||||
SELECT 1
|
||||
GET app:env # 返回 "development"
|
||||
```
|
||||
|
||||
### 数据库清空
|
||||
|
||||
```shell
|
||||
# 清空当前数据库
|
||||
FLUSHDB
|
||||
|
||||
# 异步清空当前数据库
|
||||
FLUSHDB ASYNC
|
||||
|
||||
# 清空所有数据库
|
||||
FLUSHALL
|
||||
|
||||
# 异步清空所有数据库
|
||||
FLUSHALL ASYNC
|
||||
|
||||
# 示例:安全的数据库清理
|
||||
SELECT 15 # 切换到测试数据库
|
||||
SET test:key "test_value"
|
||||
DBSIZE # 查看键数量
|
||||
FLUSHDB # 清空测试数据库
|
||||
DBSIZE # 确认清空结果
|
||||
```
|
||||
|
||||
### 数据库信息查看
|
||||
|
||||
```shell
|
||||
# 获取当前数据库键的数量
|
||||
DBSIZE
|
||||
|
||||
# 获取服务器信息
|
||||
INFO [section]
|
||||
INFO # 获取所有信息
|
||||
INFO server # 服务器信息
|
||||
INFO clients # 客户端信息
|
||||
INFO memory # 内存信息
|
||||
INFO keyspace # 键空间信息
|
||||
|
||||
# 获取配置信息
|
||||
CONFIG GET parameter
|
||||
CONFIG GET databases # 查看数据库数量配置
|
||||
CONFIG GET maxmemory # 查看最大内存配置
|
||||
|
||||
# 示例:查看各数据库使用情况
|
||||
INFO keyspace
|
||||
# 输出示例:
|
||||
# db0:keys=100,expires=10,avg_ttl=3600000
|
||||
# db1:keys=50,expires=5,avg_ttl=1800000
|
||||
```
|
||||
|
||||
## 事务操作
|
||||
|
||||
### 事务的概念
|
||||
|
||||
Redis 事务是一组命令的集合,这些命令会被顺序执行,具有以下特点:
|
||||
|
||||
**事务特性:**
|
||||
- **原子性**:事务中的命令要么全部执行,要么全部不执行
|
||||
- **一致性**:事务执行前后,数据保持一致状态
|
||||
- **隔离性**:事务执行过程中不会被其他命令干扰
|
||||
- **持久性**:事务执行结果会被持久化(如果启用了持久化)
|
||||
|
||||
**Redis 事务限制:**
|
||||
- 不支持回滚
|
||||
- 命令错误不会影响其他命令执行
|
||||
- 不支持嵌套事务
|
||||
|
||||
### MULTI/EXEC 命令
|
||||
|
||||
**基本事务操作**
|
||||
|
||||
```shell
|
||||
# 开始事务
|
||||
MULTI
|
||||
|
||||
# 添加命令到事务队列
|
||||
SET account:1001:balance 1000
|
||||
SET account:1002:balance 500
|
||||
DECRBY account:1001:balance 100
|
||||
INCRBY account:1002:balance 100
|
||||
|
||||
# 执行事务
|
||||
EXEC
|
||||
|
||||
# 取消事务
|
||||
# DISCARD
|
||||
```
|
||||
|
||||
**完整事务示例**
|
||||
|
||||
```shell
|
||||
# 银行转账事务示例
|
||||
MULTI
|
||||
GET account:1001:balance # 检查余额
|
||||
DECRBY account:1001:balance 100
|
||||
INCRBY account:1002:balance 100
|
||||
SET transfer:log "1001->1002:100"
|
||||
EXEC
|
||||
|
||||
# 批量用户创建事务
|
||||
MULTI
|
||||
HMSET user:2001 name "用户A" email "usera@example.com" status "active"
|
||||
HMSET user:2002 name "用户B" email "userb@example.com" status "active"
|
||||
SADD active_users "user:2001" "user:2002"
|
||||
INCR total_users
|
||||
EXEC
|
||||
```
|
||||
|
||||
**事务错误处理**
|
||||
|
||||
```shell
|
||||
# 语法错误示例(事务不会执行)
|
||||
MULTI
|
||||
SET key1 value1
|
||||
INVALID_COMMAND # 语法错误
|
||||
SET key2 value2
|
||||
EXEC # 返回错误,事务不执行
|
||||
|
||||
# 运行时错误示例(其他命令仍会执行)
|
||||
MULTI
|
||||
SET string_key "hello"
|
||||
LPUSH string_key "world" # 类型错误,但不影响其他命令
|
||||
SET another_key "value"
|
||||
EXEC # 部分命令执行成功
|
||||
```
|
||||
|
||||
### WATCH 命令
|
||||
|
||||
WATCH 命令用于实现乐观锁,监视键的变化。
|
||||
|
||||
**基本用法**
|
||||
|
||||
```shell
|
||||
# 监视键
|
||||
WATCH key [key ...]
|
||||
WATCH account:1001:balance account:1002:balance
|
||||
|
||||
# 开始事务
|
||||
MULTI
|
||||
DECRBY account:1001:balance 100
|
||||
INCRBY account:1002:balance 100
|
||||
EXEC # 如果被监视的键发生变化,事务不会执行
|
||||
|
||||
# 取消监视
|
||||
UNWATCH
|
||||
```
|
||||
|
||||
**乐观锁实现**
|
||||
|
||||
```shell
|
||||
# 实现安全的计数器增加
|
||||
WATCH counter
|
||||
val=$(redis-cli GET counter)
|
||||
if [ "$val" -lt 100 ]; then
|
||||
redis-cli MULTI
|
||||
redis-cli INCR counter
|
||||
redis-cli EXEC
|
||||
else
|
||||
redis-cli UNWATCH
|
||||
echo "计数器已达到上限"
|
||||
fi
|
||||
```
|
||||
|
||||
**复杂事务示例**
|
||||
|
||||
```shell
|
||||
# 库存扣减事务(防止超卖)
|
||||
WATCH product:1001:stock
|
||||
stock=$(redis-cli GET product:1001:stock)
|
||||
if [ "$stock" -ge 1 ]; then
|
||||
redis-cli MULTI
|
||||
redis-cli DECR product:1001:stock
|
||||
redis-cli LPUSH order:queue "order:$(date +%s)"
|
||||
redis-cli INCR sales:total
|
||||
result=$(redis-cli EXEC)
|
||||
if [ "$result" != "" ]; then
|
||||
echo "购买成功"
|
||||
else
|
||||
echo "购买失败,请重试"
|
||||
fi
|
||||
else
|
||||
redis-cli UNWATCH
|
||||
echo "库存不足"
|
||||
fi
|
||||
```
|
||||
|
||||
### 事务的特性和限制
|
||||
|
||||
**事务特性验证**
|
||||
|
||||
```shell
|
||||
# 原子性验证
|
||||
SET test:atomic "initial"
|
||||
MULTI
|
||||
SET test:atomic "step1"
|
||||
SET test:atomic "step2"
|
||||
SET test:atomic "final"
|
||||
EXEC
|
||||
GET test:atomic # 返回 "final"
|
||||
|
||||
# 隔离性验证(在事务执行期间,其他客户端的命令不会干扰)
|
||||
# 客户端1:
|
||||
MULTI
|
||||
SET test:isolation "value1"
|
||||
# 暂停,不执行EXEC
|
||||
|
||||
# 客户端2:
|
||||
SET test:isolation "value2" # 这个命令会立即执行
|
||||
|
||||
# 客户端1继续:
|
||||
EXEC
|
||||
GET test:isolation # 返回 "value1"(事务中的值覆盖了客户端2的修改)
|
||||
```
|
||||
|
||||
**事务限制示例**
|
||||
|
||||
```shell
|
||||
# 无回滚特性
|
||||
SET balance 1000
|
||||
MULTI
|
||||
DECRBY balance 100 # 成功
|
||||
LPUSH balance "error" # 类型错误,但不影响前面的命令
|
||||
DECRBY balance 50 # 成功
|
||||
EXEC
|
||||
GET balance # 返回 "850"(前面和后面的命令都执行了)
|
||||
|
||||
# 条件执行限制(Redis事务不支持if-else逻辑)
|
||||
# 需要在应用层实现条件判断
|
||||
balance=$(redis-cli GET account:balance)
|
||||
if [ "$balance" -gt 100 ]; then
|
||||
redis-cli MULTI
|
||||
redis-cli DECRBY account:balance 100
|
||||
redis-cli SET last:transaction "withdraw:100"
|
||||
redis-cli EXEC
|
||||
else
|
||||
echo "余额不足"
|
||||
fi
|
||||
```
|
||||
|
||||
## 脚本操作
|
||||
|
||||
### Lua 脚本简介
|
||||
|
||||
Redis 内嵌了 Lua 解释器,支持执行 Lua 脚本。Lua 脚本的优势:
|
||||
|
||||
**主要优势:**
|
||||
- **原子性**:脚本执行过程中不会被其他命令干扰
|
||||
- **减少网络开销**:多个命令在服务器端执行
|
||||
- **复杂逻辑**:支持条件判断、循环等复杂逻辑
|
||||
- **性能优化**:避免多次网络往返
|
||||
|
||||
**使用场景:**
|
||||
- 复杂的原子操作
|
||||
- 条件判断和循环
|
||||
- 批量数据处理
|
||||
- 限流算法实现
|
||||
- 分布式锁
|
||||
|
||||
### EVAL 和 EVALSHA 命令
|
||||
|
||||
**EVAL 命令基本用法**
|
||||
|
||||
```shell
|
||||
# EVAL script numkeys key [key ...] arg [arg ...]
|
||||
# script: Lua脚本
|
||||
# numkeys: 键的数量
|
||||
# key: 键名
|
||||
# arg: 参数
|
||||
|
||||
# 简单示例:设置键值并返回
|
||||
EVAL "return redis.call('SET', KEYS[1], ARGV[1])" 1 mykey myvalue
|
||||
|
||||
# 获取并增加计数器
|
||||
EVAL "local val = redis.call('GET', KEYS[1]) or 0; return redis.call('INCR', KEYS[1])" 1 counter
|
||||
|
||||
# 条件设置(仅当键不存在时设置)
|
||||
EVAL "if redis.call('EXISTS', KEYS[1]) == 0 then return redis.call('SET', KEYS[1], ARGV[1]) else return nil end" 1 newkey newvalue
|
||||
```
|
||||
|
||||
|
||||
**EVALSHA 命令**
|
||||
|
||||
```shell
|
||||
# 加载脚本并获取SHA1值
|
||||
SCRIPT LOAD "return redis.call('GET', KEYS[1])"
|
||||
# 返回:"6b1bf486c81ceb7edf3c093f4c48582e38c0e791"
|
||||
|
||||
# 使用SHA1值执行脚本
|
||||
EVALSHA 6b1bf486c81ceb7edf3c093f4c48582e38c0e791 1 mykey
|
||||
|
||||
# 检查脚本是否存在
|
||||
SCRIPT EXISTS sha1 [sha1 ...]
|
||||
SCRIPT EXISTS 6b1bf486c81ceb7edf3c093f4c48582e38c0e791
|
||||
|
||||
# 清除脚本缓存
|
||||
SCRIPT FLUSH
|
||||
|
||||
# 杀死正在执行的脚本
|
||||
SCRIPT KILL
|
||||
```
|
||||
|
||||
### 脚本缓存
|
||||
|
||||
Redis 会缓存已执行的脚本,提高重复执行的性能。
|
||||
|
||||
```shell
|
||||
# 预加载常用脚本
|
||||
incr_script_sha=$(redis-cli SCRIPT LOAD "return redis.call('INCR', KEYS[1])")
|
||||
echo "增加计数器脚本SHA: $incr_script_sha"
|
||||
|
||||
# 使用缓存的脚本
|
||||
redis-cli EVALSHA $incr_script_sha 1 my_counter
|
||||
redis-cli EVALSHA $incr_script_sha 1 my_counter
|
||||
redis-cli EVALSHA $incr_script_sha 1 my_counter
|
||||
|
||||
# 检查脚本缓存状态
|
||||
redis-cli SCRIPT EXISTS $incr_script_sha
|
||||
|
||||
# 获取脚本缓存统计
|
||||
redis-cli INFO memory | grep script
|
||||
```
|
||||
|
||||
## 实践操作
|
Reference in New Issue
Block a user