Redis 缓存、队列、排行榜的核心用法

一、Redis 是什么?

Redis 全称 Remote Dictionary Server ,是一个开源的内存数据库。与 MySQL 这类把数据存在磁盘上的数据库不同,Redis 把数据存在内存中,因此读写速度极快,通常可以达到每秒数十万次操作。

它的主要特点:

  • 速度极快:基于内存操作,读写延迟在微秒级
  • 数据结构丰富:不只是简单的 key-value,支持字符串、列表、哈希、集合、有序集合等
  • 支持持久化:可以将内存数据定期保存到磁盘,防止重启后数据丢失
  • 支持过期时间:每个 key 可以设置 TTL,到期自动删除
  • 单线程模型:命令执行是串行的,天然避免并发写入冲突

二、核心数据结构

Redis 不是只会存字符串,它有 5 种基础数据类型,每种都针对特定场景设计。

1. String(字符串)

最基本的类型,可以存文本、数字、甚至序列化后的 JSON。

复制代码
SET username "张三"
GET username          # 返回 "张三"
SET counter 0
INCR counter          # 自增,返回 1,常用于计数器
EXPIRE username 3600  # 设置 1 小时后过期

2. Hash(哈希)

类似一个小型 Map,适合存储对象。

复制代码
HSET user:1 name "张三" age 28 city "北京"
HGET user:1 name      # 返回 "张三"
HGETALL user:1        # 返回所有字段

3. List(列表)

有序的字符串列表,支持从头部或尾部插入/弹出,天然适合做队列。

复制代码
RPUSH task "任务A"    # 从右侧入队
RPUSH task "任务B"
LPOP task             # 从左侧出队,返回 "任务A"

4. Set(集合)

无序、不重复的字符串集合,支持交集、并集、差集操作。

复制代码
SADD online_users "user1" "user2" "user3"
SISMEMBER online_users "user1"  # 判断是否在线
SCARD online_users              # 在线人数

5. ZSet(有序集合)

在 Set 基础上,每个元素附带一个分数(score),按分数自动排序。排行榜的核心就靠它。

复制代码
ZADD leaderboard 9800 "玩家A"
ZADD leaderboard 12000 "玩家B"
ZREVRANGE leaderboard 0 9 WITHSCORES  # 取前10名,从高到低

三、典型场景一:缓存

这是 Redis 最经典的用途。当用户频繁请求同一份数据(比如商品详情页),每次都去查数据库既慢又浪费资源。解决思路是:第一次查数据库,结果存入 Redis,后续直接从 Redis 读取

复制代码
用户请求 → 查 Redis
              ↓ 命中?
           是 → 直接返回(毫秒级)
           否 → 查 MySQL → 写入 Redis → 返回

伪代码示意(Java/Python 风格):

复制代码
def get_product(product_id):
    cache_key = f"product:{product_id}"
    
    # 先查缓存
    result = redis.get(cache_key)
    if result:
        return json.loads(result)
    
    # 缓存未命中,查数据库
    product = db.query("SELECT * FROM products WHERE id = ?", product_id)
    
    # 写入缓存,设置 10 分钟过期
    redis.setex(cache_key, 600, json.dumps(product))
    
    return product

注意几个常见问题:

  • 缓存穿透:查询一个根本不存在的 key,每次都打到数据库。解决:对空结果也缓存,或使用布隆过滤器。
  • 缓存击穿:某个热点 key 突然过期,大量请求同时打到数据库。解决:设置互斥锁,只让一个请求去查库。
  • 缓存雪崩:大量 key 同时过期。解决:过期时间加随机抖动。

四、典型场景二:消息队列

利用 List 的 LPUSH / RPOP 特性,可以实现一个简单的消息队列,将耗时任务异步处理。

场景举例:用户注册后发送欢迎邮件。发邮件可能需要几秒,不能让用户等着。

复制代码
用户注册 → 将"发邮件任务"RPUSH 进 Redis List
                      ↓
后台 Worker 循环 LPOP 取任务 → 发送邮件

# 生产者:注册时将任务入队
def register(user):
    db.save(user)
    redis.rpush("email_queue", json.dumps({"to": user.email, "type": "welcome"}))

# 消费者:后台 Worker 持续处理
while True:
    task = redis.blpop("email_queue", timeout=5)  # 阻塞式取任务
    if task:
        send_email(json.loads(task[1]))

注意:Redis 的 List 队列适合轻量任务。如果业务复杂、需要消息确认、重试机制,建议使用 RabbitMQ 或 Kafka。


五、典型场景三:排行榜

ZSet(有序集合)天生为排行榜而生。score 存分数,member 存用户 ID,Redis 自动维护排序。

复制代码
# 更新分数(游戏得分、销售额等)
ZINCRBY leaderboard 500 "user:1001"   # user:1001 加 500 分

# 查询前 10 名
ZREVRANGE leaderboard 0 9 WITHSCORES

# 查询某个用户的排名
ZREVRANK leaderboard "user:1001"      # 返回名次(从0开始)

# 查询某个用户的分数
ZSCORE leaderboard "user:1001"

这套操作的时间复杂度是 O(log N),即使有百万用户,查询依然飞快。


六、Redis 在项目中的典型架构位置

复制代码
客户端
  ↓
后端服务(Spring Boot / Django 等)
  ↓          ↓
Redis      MySQL
(缓存/队列) (持久存储)

Redis 不是用来替代 MySQL 的,而是配合数据库使用,承担高频读写的部分,减轻数据库压力。


总结

场景 用到的数据结构 核心命令
缓存 String SET / GET / SETEX
消息队列 List RPUSH / BLPOP
排行榜 ZSet ZADD / ZREVRANGE / ZREVRANK
在线用户 Set SADD / SCARD
存储对象 Hash HSET / HGETALL

Redis 的学习曲线不陡,但要用好它,需要理解每种数据结构背后的设计意图。建议从缓存场景入手,在实际项目中逐步积累经验。

相关推荐
电商API_180079052472 小时前
反向海淘是什么?现状如何?未来趋势如何?
数据库·人工智能·笔记·性能优化·数据挖掘·网络爬虫
Trouvaille ~2 小时前
【Redis篇】Redis 安装与启动:快速搭建一个 Redis 环境
数据库·redis·后端·ubuntu·缓存·环境搭建·安装教程
fengxin_rou2 小时前
【Feed 高并发架构实战】:雪花 ID + 三级缓存 + 计数旁路设计详解
数据库·redis·缓存·架构·事务·并发
廿一夏11 小时前
MySql存储引擎与索引
数据库·sql·mysql
Mahir0811 小时前
Spring 循环依赖深度解密:从问题本质到三级缓存源码级解析
java·后端·spring·缓存·面试·循环依赖·三级缓存
曲幽11 小时前
我用了FastApiAdmin后,连夜把踩过的坑都整理出来了
redis·python·postgresql·vue3·fastapi·web·sqlalchemy·admin·fastapiadmin
lzhdim13 小时前
SQL 入门 15:SQL 事务:从 ACID 到四种常见的并发问题
数据库·sql
瀚高PG实验室13 小时前
瀚高企业版V9.1.1在pg_restore还原备份文件时提示extract函数语法问题
数据库·瀚高数据库
TDengine (老段)13 小时前
TDengine Tag 设计哲学与 Schema 变更机制
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据