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

相关推荐
猫咪很可爱19 分钟前
Oracle RAC 启动失败排查:私网通信与内核参数优化实战
运维·数据库·oracle
我不会起名字32232 分钟前
Redis 从 0 到 1(九):主库宕机 30 秒自动切主——1 主 2 从 3 哨兵 + Go 客户端
redis·docker·sentinel·高可用·哨兵
XLYcmy33 分钟前
《数字经济赋能城市低碳治理的路径研究检索报告》审阅与修改指导意见——基于完整检索报告体例的完整性诊断、学术规范核查与方法论纠偏 上
数据库·ai·chatgpt·文心一言·检索·知网·豆包
泡海椒42 分钟前
JQuick-SQL 快速开始:注册内存表并执行查询
数据库·windows·sql
ss2731 小时前
PG实战笔记 | 09 PostgreSQL psql客户端基本操作
数据库·笔记·postgresql
电商API_180079052471 小时前
反向海淘多币种结算:汇率该在哪个时点被冻结
java·开发语言·数据库·跨境电商·1688 api
搞AI的金鱼2 小时前
skill agent workflow的区别
数据库
墨子夕2 小时前
创新的潮汐——从科学发现到资本周期的百年规律(第二卷)
大数据·数据库·人工智能
Y3815326622 小时前
印度电商数据采集教程:用 SerpBase 查 Flipkart/Myntra/Ajio 商品(附代码)
数据库·python
企业数字化笔记2 小时前
多租户配额怎么控制?用量口径、并发预留与超额处理的实现方法
java·数据库·spring boot