Redis 数据结构和使用详解(带示例)

Redis 支持的主要数据结构及其对应操作命令的详细解释,结合具体使用场景和示例:


1. 字符串(String)

  • 用途:存储文本、数值或二进制数据,适用于缓存、计数器等。

  • 常用命令

    • SET key value:设置键值对。
    • GET key:获取键对应的值。
    • INCR key:将键的值递增1(原子操作)。
    • EXPIRE key seconds:设置键的过期时间。
  • 示例

    SET user:1001:name "Alice"  # 存储用户名
    GET user:1001:name           # 返回 "Alice"
    INCR article:123:views       # 文章阅读量+1
    
  • 场景 1:缓存用户 Token

    # 存储 Token,有效期 1 小时
    SET user:1001:token "abc123" EX 3600
    # 返回:OK
    
    # 获取 Token
    GET user:1001:token
    # 返回:"abc123"
    
    # 检查剩余过期时间
    TTL user:1001:token
    # 返回:3590(剩余秒数)
    
  • 场景 2:计数器(文章阅读量)

    # 初始化阅读量
    SET article:2001:views 0
    # 返回:OK
    
    # 阅读量 +1
    INCR article:2001:views
    # 返回:1(递增后的值)
    
    # 批量递增(+5)
    INCRBY article:2001:views 5
    # 返回:6
    
  • 场景 3:分布式锁

    # 尝试获取锁(有效期 10 秒)
    SET order:lock "process123" NX PX 10000
    # 返回:OK(获取成功)或 nil(失败)
    
    # 释放锁(需值匹配)
    EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 order:lock process123
    # 返回:1(删除成功)或 0(失败)
    

2. 哈希(Hash)

  • 用途:存储对象字段,适合保存用户信息、商品属性等结构化数据。

  • 常用命令

    • HSET key field value:设置哈希字段值。
    • HGET key field:获取哈希字段值。
    • HGETALL key:获取所有字段和值。
  • 示例

    HSET user:1001 age 30 email "alice@example.com"  # 存储用户信息
    HGET user:1001 age                               # 返回 "30"
    HGETALL user:1001                                # 返回所有字段和值
    
  • 场景 1:存储用户信息

    # 添加用户字段
    HSET user:1001 name "Alice" age 30 email "alice@example.com"
    # 返回:3(添加的字段数)
    
    # 获取单个字段
    HGET user:1001 name
    # 返回:"Alice"
    
    # 获取所有字段
    HGETALL user:1001
    # 返回:
    # 1) "name"
    # 2) "Alice"
    # 3) "age"
    # 4) "30"
    # 5) "email"
    # 6) "alice@example.com"
    
  • 场景 2:商品库存管理

    # 设置商品库存
    HSET product:5001 stock 100 price 2999
    # 返回:2
    
    # 扣减库存(原子操作)
    HINCRBY product:5001 stock -1
    # 返回:99
    
    # 获取价格
    HGET product:5001 price
    # 返回:"2999"
    
  • 场景 3:配置中心

    # 存储服务配置
    HSET service:config timeout 5000 retry 3 enable_cache true
    # 返回:3
    
    # 修改配置
    HSET service:config timeout 10000
    # 返回:0(字段已存在,仅更新)
    
    # 删除配置字段
    HDEL service:config retry
    # 返回:1
    

3. 列表(List)

  • 用途:实现消息队列、最新消息列表(如微博时间线)。

  • 常用命令

    • LPUSH key value:从列表左侧插入元素。
    • RPOP key:从列表右侧弹出元素。
    • LRANGE key start end:获取列表范围内的元素。
  • 示例

    LPUSH news:latest "Article 1"  # 插入最新新闻
    LPUSH news:latest "Article 2"
    LRANGE news:latest 0 4         # 获取前5条新闻
    
  • 场景 1:消息队列

    # 生产者推送任务
    LPUSH task:queue "send_email:user1" "generate_report:user2"
    # 返回:2(队列长度)
    
    # 消费者获取任务
    RPOP task:queue
    # 返回:"send_email:user1"
    
    # 查看队列剩余任务
    LRANGE task:queue 0 -1
    # 返回:1) "generate_report:user2"
    
  • 场景 2:最新消息列表

    # 插入最新新闻
    LPUSH news:latest "Article 3" "Article 2" "Article 1"
    # 返回:3
    
    # 获取前 2 条新闻
    LRANGE news:latest 0 1
    # 返回:
    # 1) "Article 1"
    # 2) "Article 2"
    
  • 场景 3:阻塞队列

    # 消费者阻塞等待任务(超时 10 秒)
    BRPOP task:queue 10
    # 返回(如果有任务):
    # 1) "task:queue"
    # 2) "generate_report:user2"
    

4. 集合(Set)

  • 用途:存储唯一元素,支持交集、并集操作(如共同好友、标签系统)。

  • 常用命令

    • SADD key member:添加元素到集合。
    • SMEMBERS key:获取集合所有元素。
    • SINTER key1 key2:计算多个集合的交集。
  • 示例

    SADD user:1001:follows 2001 2002  # 用户1001关注2001和2002
    SADD user:1002:follows 2001 2003
    SINTER user:1001:follows user:1002:follows  # 返回共同关注用户2001
    
  • 场景 1:标签系统

    # 添加文章标签
    SADD article:3001:tags "tech" "redis" "database"
    # 返回:3
    
    # 查找共同标签
    SINTER article:3001:tags article:3002:tags
    # 返回(假设 article:3002 有 "tech" 和 "cloud"):
    # 1) "tech"
    
  • 场景 2:抽奖活动

    # 添加参与者
    SADD lottery:2023 "user100" "user200" "user300"
    # 返回:3
    
    # 随机抽取 1 名中奖者
    SRANDMEMBER lottery:2023
    # 返回:"user200"(随机结果)
    
    # 移除并返回中奖者
    SPOP lottery:2023
    # 返回:"user100"
    
  • 场景 3:黑白名单

    # 添加黑名单用户
    SADD blacklist:ip "192.168.1.1" "192.168.1.2"
    # 返回:2
    
    # 检查 IP 是否在黑名单
    SISMEMBER blacklist:ip "192.168.1.1"
    # 返回:1(存在)
    

5. 有序集合(Sorted Set)

  • 用途:排行榜、优先级队列(按分数排序)。

  • 常用命令

    • ZADD key score member:添加带分数的成员。
    • ZRANGE key start end [WITHSCORES]:按分数升序返回成员。
    • ZREVRANGE key start end:按分数降序返回成员。
  • 示例

    ZADD game:leaderboard 1500 "PlayerA"  # 添加玩家分数
    ZADD game:leaderboard 2000 "PlayerB"
    ZREVRANGE game:leaderboard 0 9 WITHSCORES  # 返回前10名玩家
    
  • 场景 1:游戏排行榜

    # 添加玩家分数
    ZADD game:leaderboard 1500 "PlayerA" 2000 "PlayerB" 1800 "PlayerC"
    # 返回:3
    
    # 获取前 3 名(降序)
    ZREVRANGE game:leaderboard 0 2 WITHSCORES
    # 返回:
    # 1) "PlayerB"
    # 2) "2000"
    # 3) "PlayerC"
    # 4) "1800"
    # 5) "PlayerA"
    # 6) "1500"
    
  • 场景 2:延时任务

    # 添加任务(时间戳为分数)
    ZADD tasks:delayed 1672531200 "task1" 1672617600 "task2"
    # 返回:2
    
    # 获取当前需处理的任务(分数 <= 当前时间戳)
    ZRANGEBYSCORE tasks:delayed -inf 1672531200
    # 返回:1) "task1"
    
  • 场景 3:热搜榜单

    # 更新关键词热度
    ZINCRBY hot:keywords 1 "redis"
    # 返回:"1"(当前分数)
    
    ZINCRBY hot:keywords 1 "java"
    # 返回:"1"
    
    # 获取 Top 10 热搜词
    ZREVRANGE hot:keywords 0 9 WITHSCORES
    # 返回:
    # 1) "redis"
    # 2) "1"
    # 3) "java"
    # 4) "1"
    

6. 地理位置(GEO)

  • 用途:存储和查询地理位置(附近的人、商家)。

  • 常用命令

    • GEOADD key longitude latitude member:添加地理坐标。
    • GEODIST key member1 member2 [unit]:计算两地距离。
    • GEORADIUS key longitude latitude radius unit:查找范围内的成员。
  • 示例

    GEOADD restaurants 116.404269 39.913818 "RestaurantA"  # 添加餐厅坐标
    GEORADIUS restaurants 116.405 39.914 2 km WITHDIST      # 查找2公里内的餐厅
    
  • 场景 1:附近餐厅查询

    # 添加餐厅坐标
    GEOADD restaurants 116.404269 39.913818 "RestaurantA" 116.407531 39.915264 "RestaurantB"
    # 返回:2
    
    # 查找 1 公里内的餐厅
    GEORADIUS restaurants 116.405285 39.912987 1 km WITHDIST
    # 返回:
    # 1) 1) "RestaurantA"
    #    2) "0.8923"
    
  • 场景 2:计算距离

    # 计算两餐厅距离
    GEODIST restaurants "RestaurantA" "RestaurantB" km
    # 返回:"0.312"(公里)
    
  • 场景 3:获取坐标

    # 获取餐厅坐标
    GEOPOS restaurants "RestaurantA"
    # 返回:
    # 1) 1) "116.404269"
    #    2) "39.913818"
    

7. 位图(Bitmap)

  • 用途:位操作(如用户签到、活跃统计)。

  • 常用命令

    • SETBIT key offset value:设置位的值(0或1)。
    • GETBIT key offset:获取位的值。
    • BITCOUNT key:统计值为1的位数。
  • 示例

    SETBIT user:1001:sign:202310 5 1  # 用户1001在10月6日签到
    BITCOUNT user:1001:sign:202310    # 统计本月签到天数
    
  • 场景 1:用户签到

    # 用户 1001 在 10 月 1 日签到(偏移量 0)
    SETBIT user:1001:sign:202310 0 1
    # 返回:0(之前位的值)
    
    # 检查 10 月 1 日是否签到
    GETBIT user:1001:sign:202310 0
    # 返回:1
    
  • 场景 2:活跃用户统计

    # 统计 10 月累计签到天数
    BITCOUNT user:1001:sign:202310
    # 返回:3(假设签到 3 天)
    
  • 场景 3:权限控制

    # 设置权限位(位 0: 读,位 1: 写)
    SETBIT user:1001:permissions 0 1
    SETBIT user:1001:permissions 1 0
    # 检查写权限
    GETBIT user:1001:permissions 1
    # 返回:0(无权限)
    

8. HyperLogLog

  • 用途:近似去重计数(如统计UV)。

  • 常用命令

    • PFADD key element:添加元素。
    • PFCOUNT key:统计唯一元素数量。
  • 示例

    PFADD daily_uv:20231001 "user1" "user2"  # 记录当日访问用户
    PFCOUNT daily_uv:20231001                # 返回近似UV数
    
  • 场景 1:UV 统计

    # 记录用户访问
    PFADD daily_uv:20231001 "user1" "user2" "user1"
    # 返回:1(新增唯一用户数)
    
    # 获取当日 UV
    PFCOUNT daily_uv:20231001
    # 返回:2
    
  • 场景 2:合并多日 UV

    # 合并 10 月 1 日和 2 日的 UV
    PFMERGE weekly_uv:20231001-07 daily_uv:20231001 daily_uv:20231002
    # 返回:OK
    
    # 获取周 UV
    PFCOUNT weekly_uv:20231001-07
    # 返回:5(假设两日共有 5 个唯一用户)
    

9. 流(Stream)

  • 用途:消息队列(支持消费者组、消息持久化)。

  • 常用命令

    • XADD key * field1 value1:添加消息。
    • XREAD COUNT num STREAMS key $:读取消息。
    • XGROUP CREATE key groupname $:创建消费者组。
  • 示例

    XADD order:stream * user "Alice" product "Phone"  # 发布订单消息
    XREAD COUNT 10 STREAMS order:stream 0             # 读取消息
    
  • 场景 1:订单消息队列

    # 发布订单消息
    XADD orders:* user_id 1001 product_id 2001 status "created"
    # 返回:"1672531200000-0"(消息 ID)
    
    # 读取最新消息
    XREAD COUNT 1 STREAMS orders:*
    # 返回:
    # 1) 1) "orders:*"
    #    2) 1) 1) "1672531200000-0"
    #          2) 1) "user_id"
    #             2) "1001"
    #             3) "product_id"
    #             4) "2001"
    #             5) "status"
    #             6) "created"
    
  • 场景 2:消费者组

    # 创建消费者组
    XGROUP CREATE orders:stream order_group $
    # 返回:OK
    
    # 消费者读取消息
    XREADGROUP GROUP order_group consumer1 COUNT 1 STREAMS orders:stream >
    # 返回:同上消息内容
    

10. 发布/订阅(Pub/Sub)

  • 用途:消息广播(如实时通知、聊天室)。

  • 常用命令

    • PUBLISH channel message:发布消息到频道。
    • SUBSCRIBE channel:订阅频道。
  • 示例

    SUBSCRIBE news_updates     # 订阅新闻频道
    PUBLISH news_updates "Redis 7.0 released!"  # 发布新闻
    
  • 场景 1:实时通知

    # 订阅新闻频道
    SUBSCRIBE news
    # 返回:
    # 1) "subscribe"
    # 2) "news"
    # 3) (integer) 1
    
    # 发布新闻
    PUBLISH news "Redis 7.0 released!"
    # 订阅者接收:
    # 1) "message"
    # 2) "news"
    # 3) "Redis 7.0 released!"
    
  • 场景 2:多频道订阅

    # 订阅多个频道
    PSUBSCRIBE news.*
    # 发布到 news.tech
    PUBLISH news.tech "New Redis features"
    # 订阅者接收:
    # 1) "pmessage"
    # 2) "news.*"
    # 3) "news.tech"
    # 4) "New Redis features"
    

总结

通过以上示例,可以得出如下总结:

数据结构典型场景核心命令
String缓存、计数器SET, GET, INCR
Hash对象存储HSET, HGET, HGETALL
List消息队列、最新列表LPUSH, RPOP, LRANGE
Set标签、共同好友SADD, SMEMBERS, SINTER
Sorted Set排行榜、优先级任务ZADD, ZRANGE, ZREVRANGE
GEO地理位置查询GEOADD, GEORADIUS
Bitmap用户签到、布尔统计SETBIT, GETBIT, BITCOUNT
HyperLogLog大数据去重计数PFADD, PFCOUNT
Stream消息队列(支持消费者组)XADD, XREAD, XGROUP
Pub/Sub实时消息广播PUBLISH, SUBSCRIBE

通过合理选择数据结构和命令,可以高效解决缓存、实时统计、消息通信等多样化需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值