Files
Cloud-book/数据库/Redis_2025/04_Redis基本命令.md
2025-08-27 17:10:05 +08:00

13 KiB
Raw Blame History

Redis 基本命令

Redis 提供了丰富的命令来管理键、数据库、事务和脚本。掌握这些基本命令是高效使用 Redis 的基础。

键操作命令

键的命名规范

良好的键命名规范是 Redis 应用的重要基础,有助于提高可维护性和性能。

推荐的命名规范:

  1. 使用冒号分隔层级

    user:1001:profile
    product:category:electronics
    cache:query:user_list
    session:web:abc123
    
  2. 使用有意义的前缀

    # 按功能分类
    cache:*     # 缓存数据
    session:*   # 会话数据
    config:*    # 配置信息
    temp:*      # 临时数据
    
    # 按业务分类
    user:*      # 用户相关
    order:*     # 订单相关
    product:*   # 商品相关
    
  3. 避免特殊字符

    # 推荐
    user:1001:name
    article:2023:01:15
    
    # 不推荐
    user 1001 name
    article@2023#01#15
    
  4. 保持一致性

    # 统一使用小写
    user:profile:name
    user:profile:email
    
    # 统一日期格式
    log:2024:01:15
    report:2024:01:15
    

键的查询和遍历

基本查询命令

# 检查键是否存在
# 用法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

模式匹配查询

# 查找匹配模式的键(谨慎使用)
# 用法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:*"

随机获取键

# 随机返回一个键
# 用法RANDOMKEY

# 示例:随机获取键进行采样
RANDOMKEY
RANDOMKEY
RANDOMKEY

键的过期设置

Redis 支持为键设置过期时间,这是内存管理和缓存实现的重要功能。

设置过期时间

# 设置键的过期时间(秒)
# 用法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"

查询过期时间

# 获取键的剩余生存时间(秒)
# 用法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

移除过期时间

# 移除键的过期时间,使其永久存在
# 用法PERSIST key
PERSIST session:abc123
SETEX temp_key 300 "临时数据"
TTL temp_key            # 查看过期时间
PERSIST temp_key        # 移除过期时间
TTL temp_key            # 返回-1表示永不过期

键的删除和重命名

删除键

# 删除一个或多个键
# 用法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            # 删除所有数据库所有键

重命名键

# 重命名键
# 用法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  # 失败返回0target_key已存在

数据库操作

多数据库概念

Redis 支持多个数据库默认有16个数据库编号0-15可以通过配置文件修改数量。

数据库特点:

  • 每个数据库都是独立的键空间
  • 不同数据库间的键名可以相同
  • 默认连接到数据库0
  • 数据库间不支持关联查询

使用场景:

  • 区分不同环境(开发、测试、生产)
  • 分离不同类型的数据
  • 临时数据隔离

数据库切换

# 切换到指定数据库
# 用法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"

数据库清空

# 清空当前数据库
FLUSHDB

# 异步清空当前数据库
FLUSHDB ASYNC

# 清空所有数据库
FLUSHALL

# 异步清空所有数据库
FLUSHALL ASYNC

# 示例:安全的数据库清理
SELECT 15       # 切换到测试数据库
SET test:key "test_value"
DBSIZE          # 查看键数量
FLUSHDB         # 清空测试数据库
DBSIZE          # 确认清空结果

数据库信息查看

# 获取当前数据库键的数量
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 命令

基本事务操作

# 开始事务
MULTI

# 添加命令到事务队列
SET account:1001:balance 1000
SET account:1002:balance 500
DECRBY account:1001:balance 100
INCRBY account:1002:balance 100

# 执行事务
EXEC

# 取消事务
# DISCARD

完整事务示例

# 银行转账事务示例
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

事务错误处理

# 语法错误示例(事务不会执行)
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 命令用于实现乐观锁,监视键的变化。

基本用法

# 监视键
WATCH key [key ...]
WATCH account:1001:balance account:1002:balance

# 开始事务
MULTI
DECRBY account:1001:balance 100
INCRBY account:1002:balance 100
EXEC    # 如果被监视的键发生变化,事务不会执行

# 取消监视
UNWATCH

乐观锁实现

# 实现安全的计数器增加
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

复杂事务示例

# 库存扣减事务(防止超卖)
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

事务的特性和限制

事务特性验证

# 原子性验证
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的修改

事务限制示例

# 无回滚特性
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 命令基本用法

# 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 命令

# 加载脚本并获取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 会缓存已执行的脚本,提高重复执行的性能。

# 预加载常用脚本
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

实践操作