Redis 知识点与应用场景

1. Redis 简介与核心特性

Redis(Remote Dictionary Server)是一款开源的内存数据存储系统,支持多种数据结构,兼具高性能、持久化、分布式等特性,广泛用于缓存、数据库、消息中间件等场景。其核心特性包括:

  • 高性能:基于内存操作,单线程模型避免上下文切换开销,QPS 可达 10 万 +(取决于数据大小和命令复杂度);
  • 多数据结构支持:不仅支持基础的键值对,还提供 String、Hash、List 等丰富数据类型;
  • 持久化:通过 RDB 和 AOF 机制将内存数据持久化到磁盘,防止数据丢失;
  • 高可用:支持主从复制、哨兵(Sentinel)实现故障自动转移;
  • 分布式:Redis Cluster 提供分片存储,突破单机内存限制;
  • 功能丰富:支持事务、发布订阅、Lua 脚本、地理空间等高级特性。

2. 核心数据类型及应用场景详解

Redis 提供8 种核心数据类型,每种类型针对特定场景优化,以下为详细说明:

2.1 String(字符串)

数据结构特点
  • 二进制安全:可存储文本、图片、序列化对象等任意二进制数据;
  • 最大容量:单个 String 值最大 512MB;
  • 底层实现:小字符串(<39 字节)用 SDS(简单动态字符串),大字符串用 embstr/raw 编码。
常用命令
命令 功能描述 示例
SET key value [EX seconds] 设置键值对,可选过期时间 SET user:1001 '{"name":"Alice","age":25}' EX 3600(缓存 1 小时)
GET key 获取键值 GET user:1001 → 返回用户信息 JSON
INCR key 整数自增 1(原子操作) INCR article:read:10086(文章阅读量 + 1)
DECR key 整数自减 1(原子操作) DECR stock:iphone15(库存 - 1)
APPEND key value 追加字符串到值末尾 APPEND log:user:1001 " login success"
应用场景
  • 缓存热点数据 :存储用户信息、商品详情等高频访问数据,减轻数据库压力。
    示例 :电商场景中,缓存商品详情页数据:SET product:10001 '{"id":10001,"name":"无线耳机","price":999}' EX 1800(缓存 30 分钟),用户访问时直接从 Redis 获取,无需查询 MySQL。

  • 计数器 :利用INCR/DECR的原子性,实现文章阅读量、视频播放量、接口请求次数统计。
    示例 :短视频平台统计视频播放量:用户每次观看视频时,执行INCR video:play:9527,后台定期将计数器值同步到数据库。

  • 分布式锁 :基于SET key value NX EX命令(NX:不存在才设置,EX:过期时间)实现分布式锁,防止并发操作冲突。
    示例 :秒杀场景中,通过SET lock:seckill:1001 "1" NX EX 10抢占锁,获取锁后执行库存扣减,执行完毕释放锁(DEL lock:seckill:1001)。

2.2 Hash(哈希)

数据结构特点
  • 键值对集合:一个 Hash 键包含多个field-value键值对,类似 JSON 对象;
  • 空间高效:适合存储对象,可单独操作字段(无需整体更新);
  • 底层实现:小 Hash(field 数量少且值小)用压缩列表,大 Hash 用哈希表。
常用命令
命令 功能描述 示例
HSET key field value 设置 Hash 字段值 HSET user:1001 name "Alice" age 25 email "alice@example.com"
HGET key field 获取 Hash 字段值 HGET user:1001 name → "Alice"
HMGET key field1 field2 批量获取 Hash 字段值 HMGET user:1001 name age → ["Alice", "25"]
HGETALL key 获取 Hash 所有字段和值 HGETALL user:1001 → ["name","Alice","age","25",...]
HINCRBY key field num 字段值整数自增 num(原子操作) HINCRBY user:1001 score 10(用户积分 + 10)
应用场景
  • 对象存储 :存储用户、商品等结构化数据,支持字段级更新,比 String 更灵活。
    示例 :社交平台存储用户资料:HSET user:1001 name "Bob" avatar "avatar.jpg" vip_level 3,更新头像时仅需HSET user:1001 avatar "new_avatar.jpg",无需修改整个对象。

  • 购物车 :以用户 ID 为 Hash 键,商品 ID 为 field,数量为 value,实现购物车增删改查。
    示例 :用户 1001 的购物车:HSET cart:1001 2001 2 2002 1(商品 2001 数量 2,商品 2002 数量 1),修改数量时HSET cart:1001 2001 3,清空购物车时DEL cart:1001

2.3 List(列表)

数据结构特点
  • 有序字符串列表:元素按插入顺序排列,支持两端插入 / 删除;
  • 双向链表特性:可充当栈(LIFO)或队列(FIFO);
  • 底层实现:小 List(元素少且小)用压缩列表,大 List 用双向链表。
常用命令
命令 功能描述 示例
LPUSH key value1 [value2] 从列表左侧插入元素 LPUSH msg:queue "msg1" "msg2"(左侧插入两条消息)
RPUSH key value1 [value2] 从列表右侧插入元素 RPUSH article:latest 1001 1002(右侧追加文章 ID)
LPOP key 从列表左侧弹出元素(返回并删除) LPOP msg:queue → "msg2"(栈模式:后进先出)
RPOP key 从列表右侧弹出元素(返回并删除) RPOP msg:queue → "msg1"(队列模式:先进先出)
LRANGE key start stop 获取列表指定范围元素(0 为头,-1 为尾) LRANGE article:latest 0 9 → 获取最新 10 篇文章 ID
应用场景
  • 消息队列 :基于LPUSH+RPOP实现简单的 FIFO 消息队列,生产者左侧插入消息,消费者右侧弹出消息。
    示例 :订单系统异步通知:订单创建后,LPUSH order:notify "order123",通知服务循环执行RPOP order:notify获取订单 ID 并发送短信。

  • 最新数据展示 :基于LPUSH+LRANGE实现 "最新 N 条数据" 功能,如最新文章、最近评论。
    示例 :博客平台展示最新 5 篇文章:发布文章时LPUSH article:latest 3001(文章 ID),前端调用LRANGE article:latest 0 4获取前 5 篇文章 ID,再查询详情。

2.4 Set(集合)

数据结构特点
  • 无序字符串集合:元素唯一(自动去重),不保证顺序;
  • 支持集合运算:交集、并集、差集,时间复杂度 O (N);
  • 底层实现:小 Set 用整数集合(元素为整数且少),大 Set 用哈希表。
常用命令
命令 功能描述 示例
SADD key member1 member2 向集合添加元素(自动去重) SADD user:tags:1001 "tech" "music" "sports"(用户 1001 的标签)
SMEMBERS key 获取集合所有元素 SMEMBERS user:tags:1001 → ["tech","music","sports"]
SISMEMBER key member 判断元素是否在集合中 SISMEMBER user:tags:1001 "music" → 1(存在)
SINTER key1 key2 计算两个集合的交集 SINTER user:friends:1001 user:friends:1002(共同好友)
SUNION key1 key2 计算两个集合的并集 SUNION user:tags:1001 user:tags:1002(合并标签)
SREM key member 从集合删除元素 SREM user:tags:1001 "sports"(移除标签)
应用场景
  • 标签系统 :存储用户兴趣标签、文章分类等,支持标签添加、删除、查询。
    示例 :内容平台用户标签管理:用户 1001 添加 "科技""音乐" 标签后,可通过SMEMBERS user:tags:1001获取所有标签,推荐内容时根据标签匹配。

  • 共同好友 / 兴趣 :通过SINTER计算交集,实现社交平台 "共同好友" 功能。
    示例 :用户 A(ID1001)和用户 B(ID1002)的好友列表分别为user:friends:1001user:friends:1002,执行SINTER user:friends:1001 user:friends:1002即可获取两人的共同好友 ID。

  • 去重统计 :利用集合元素唯一性,统计 UV(独立访客)、去重 ID 列表等。
    示例 :统计某活动参与用户 ID(去重):SADD activity:100:users 5001 5002 5001(自动去重后仅保留 5001、5002),SCARD activity:100:users → 2(参与人数)。

2.5 Sorted Set(ZSet,有序集合)

数据结构特点
  • 有序唯一元素:每个元素关联一个score(浮点数),按score升序排列,元素不可重复;
  • 高效排序与查询:支持按score范围、排名范围查询,底层基于 "跳跃表" 实现,时间复杂度 O (logN);
  • 支持score动态更新:修改元素score后自动调整排序位置。
常用命令
命令 功能描述 示例
ZADD key score member 添加元素及 score ZADD game:rank 95 "userA" 88 "userB" 92 "userC"(游戏排行榜)
ZRANGE key start stop [WITHSCORES] 按 score 升序获取排名范围内元素(0 为第一名) ZRANGE game:rank 0 2 WITHSCORES → ["userB",88,"userC",92,"userA",95]
ZREVRANGE key start stop [WITHSCORES] 按 score 降序获取排名范围内元素 ZREVRANGE game:rank 0 2 WITHSCORES → ["userA",95,"userC",92,"userB",88](前三名)
ZSCORE key member 获取元素 score ZSCORE game:rank "userA" → 95
ZINCRBY key increment member 元素 score 自增 increment(原子操作) ZINCRBY game:rank 5 "userB"(userB 分数 + 5 → 93)
ZRANK key member 获取元素升序排名(0 为第一名) ZRANK game:rank "userB" → 0(score 88 时排名第一)
应用场景
  • 排行榜系统 :实时展示用户积分、商品销量、视频播放量等排名。
    示例 :直播平台礼物榜:观众送礼物时,ZINCRBY gift:rank:room100 50 "user888"(用户 888 积分 + 50),前端调用ZREVRANGE gift:rank:room100 0 9 WITHSCORES展示 "房间贡献榜 TOP10"。

  • 带权重的消息队列 :按score(权重)优先级消费消息,高权重消息优先处理。
    示例 :订单处理系统:普通订单ZADD order:queue 1 "order1001",VIP 订单ZADD order:queue 10 "order1002",消费者通过ZREVRANGE order:queue 0 0优先获取 VIP 订单处理。

  • 范围统计 :按score范围筛选元素,如 "积分> 1000 的用户""考试分数 80-90 分的学生"。
    示例 :教育平台统计成绩:ZRANGEBYSCORE exam:math 80 90 → 获取数学成绩 80-90 分的学生 ID。

3. 高级数据类型

3.1 Bitmap(位图)

数据结构特点
  • 位级操作:将字符串视为 "位数组",每个位(bit)表示一个二值状态(0/1);
  • 空间高效:1 字节 = 8 位,存储 100 万个状态仅需约 125KB;
  • 支持位运算:与(AND)、或(OR)、异或(XOR)、非(NOT)及位计数。
常用命令
命令 功能描述 示例
SETBIT key offset value 设置指定偏移量的位值(0/1) SETBIT sign:user:1001 5 1(用户 1001 第 5 天签到,偏移量从 0 开始)
GETBIT key offset 获取指定偏移量的位值 GETBIT sign:user:1001 5 → 1(第 5 天已签到)
BITCOUNT key [start end] 统计位值为 1 的数量(可指定字节范围) BITCOUNT sign:user:1001 → 15(本月累计签到 15 天)
BITOP op destkey key1 [key2] 对多个 Bitmap 执行位运算,结果存到 destkey BITOP AND sign:both:1001_1002 sign:user:1001 sign:user:1002(两人共同签到的天数)
应用场景
  • 签到统计 :记录用户每日签到状态,统计每月签到天数、连续签到天数。
    示例 :用户 1001 的 2025 年 8 月签到:SETBIT sign:user:1001:202508 0 1(8 月 1 日签到,偏移量 0)、SETBIT ... 2 1(8 月 3 日签到),BITCOUNT sign:user:1001:202508 → 2(当月签到 2 天)。

  • 用户在线状态 :用位偏移量表示用户 ID,位值 1 表示在线,0 表示离线,高效统计在线人数。
    示例 :平台在线用户:用户 5001 在线 → SETBIT online:20250814 5001 1BITCOUNT online:20250814 → 1000(当前在线人数)。

3.2 HyperLogLog(基数统计)

数据结构特点
  • 基数估算:用于统计 "集合中不重复元素的个数"(基数),而非存储元素本身;
  • 空间极致优化:无论基数多大,单个 HyperLogLog 键仅占用约 12KB 内存;
  • 概率性算法:存在 0.81% 的误差(可接受范围内),适合海量数据基数统计。
常用命令
命令 功能描述 示例
PFADD key element1 [element2] 添加元素到 HyperLogLog PFADD uv:20250814 1001 1002 1001 1003(网站当日 UV 统计)
PFCOUNT key 估算基数(不重复元素个数) PFCOUNT uv:20250814 → 3(去重后 1001、1002、1003)
PFMERGE destkey key1 [key2] 合并多个 HyperLogLog 到 destkey PFMERGE uv:202508 uv:20250801 uv:20250802 ...(合并 8 月每日 UV,统计月 UV)
应用场景
  • UV 统计 :统计网站 / 页面的独立访客数,无需存储用户 ID,节省内存。
    示例 :电商首页 UV:用户访问时PFADD uv:home:20250814 <user_id>,当日结束后PFCOUNT uv:home:20250814 → 50000(首页当日 UV)。

  • 搜索关键词去重 :统计用户搜索过的不重复关键词数量,优化搜索推荐。
    示例PFADD search:keywords "phone" "book" "phone" "shoes"PFCOUNT search:keywords → 3(不重复关键词数)。

3.3 Geospatial(地理空间)

数据结构特点
  • 地理位置存储:存储经纬度坐标(经度范围 - 180~180,纬度范围 - 85.05112878~85.05112878),支持距离计算、范围查询;
  • 底层基于 ZSet 实现:将经纬度编码为score(Geohash 算法),通过 ZSet 命令间接操作。
常用命令
命令 功能描述 示例
GEOADD key longitude latitude member 添加地理位置 GEOADD shops 116.403 39.914 "storeA" 116.410 39.905 "storeB"(北京商店坐标)
GEODIST key member1 member2 [unit] 计算两个位置的距离(unit:m/km/mi/ft) GEODIST shops storeA storeB km → 1.2(storeA 与 storeB 相距 1.2 公里)
GEORADIUS key longitude latitude radius unit [WITHDIST] 搜索指定坐标半径内的位置 GEORADIUS shops 116.4 39.9 5 km WITHDIST → 获取天安门 5 公里内的商店及距离
应用场景
  • 附近的人 / 地点 :基于用户当前坐标,搜索周边一定范围内的人或商家。
    示例 :外卖平台 "附近商家":用户坐标(116.4, 39.9),GEORADIUS shops 116.4 39.9 3 km WITHDIST → 返回 3 公里内的商家及距离,按距离排序展示。

  • 地理位置围栏 :监控设备是否进入 / 离开指定区域(如物流包裹是否到达配送范围)。
    示例 :物流场景中,GEORADIUS warehouse:1 120.0 30.0 10 km → 检查 10 公里内是否有包裹(通过包裹 ID 关联的坐标),触发配送通知。

3.4 Stream(消息流)

数据结构特点
  • 持久化消息队列:支持消息持久化、消费确认、消费组(Consumer Group),解决 List 作为队列时的消息丢失、重复消费问题;
  • 消息 ID 自增:每条消息有唯一 ID(格式timestamp-sequence,如1723600000000-0),保证有序性;
  • 消费组机制:支持多消费者协同消费,每个消费者处理不同消息,避免重复消费。
常用命令
命令 功能描述 示例
XADD key * field value [field value] 添加消息(* 表示自动生成 ID) XADD orderStream * type "pay" orderId "123" amount 99(订单支付消息)
XREAD COUNT count STREAMS key startId 读取消息(startId=0-0 表示从头读) XREAD COUNT 1 STREAMS orderStream 0-0 → 读取 1 条消息
XGROUP CREATE key groupName startId 创建消费组 XGROUP CREATE orderStream group1 $($ 表示从最新消息开始消费)
XREADGROUP GROUP groupName consumer COUNT count STREAMS key > 消费组内消费者读取消息(> 表示未消费消息) XREADGROUP GROUP group1 consumer1 COUNT 1 STREAMS orderStream > → consumer1 读取 1 条未消费消息
XACK key groupName msgId 确认消息已消费 XACK orderStream group1 1723600000000-0(确认消息处理完成)
应用场景
  • 可靠消息队列 :替代 List 实现高可靠消息传递,支持消息重试、消费确认,适合订单处理、日志收集等场景。
    示例 :电商订单系统:订单支付后XADD payStream * orderId "123" status "success",下游物流服务通过消费组XREADGROUP读取消息并处理,处理完成后XACK确认,避免消息丢失。

4. 持久化机制(RDB vs AOF)

Redis 支持两种持久化方式,可单独启用或混合使用,核心目标是防止内存数据丢失。

4.1 RDB(Redis Database)

  • 原理 :在指定时间间隔内生成内存数据的快照文件(.rdb),保存到磁盘。
  • 触发方式
    • 手动触发:SAVE(阻塞 Redis,适合离线备份)、BGSAVE(fork 子进程执行,不阻塞主进程);
    • 自动触发:配置文件中save <seconds> <changes>(如save 3600 1:3600 秒内有 1 次修改则触发)。
  • 优缺点
    • 优点:文件体积小,恢复速度快(直接加载快照到内存);
    • 缺点:数据安全性低,两次快照间的修改可能丢失(如 5 分钟快照间隔,崩溃时丢失 5 分钟数据)。

4.2 AOF(Append Only File)

  • 原理 :记录所有写命令(如 SET、HSET)到日志文件(.aof),重启时通过重新执行命令恢复数据。
  • 配置参数
    • appendfsync always:每条命令立即刷盘(安全性最高,性能最差);
    • appendfsync everysec:每秒刷盘一次(默认,平衡安全与性能,最多丢失 1 秒数据);
    • appendfsync no:由操作系统决定刷盘时机(性能最好,安全性最低)。
  • AOF 重写 :解决 AOF 文件膨胀问题,通过BGREWRITEAOF命令生成新 AOF 文件(合并重复命令,如多次 INCR 合并为最终值)。
  • 优缺点
    • 优点:数据安全性高,丢失数据少;
    • 缺点:文件体积大,恢复速度慢(需重新执行所有命令)。

4.3 混合持久化(Redis 4.0+)

  • 原理:AOF 文件头部存储 RDB 快照,尾部存储增量 AOF 命令,结合 RDB 恢复快和 AOF 数据全的优点。
  • 配置aof-use-rdb-preamble yes(默认开启)。

4.4 持久化方案选择

场景 推荐方案 理由
数据安全性要求高(如金融交易) AOF(everysec)+ 混合持久化 最多丢失 1 秒数据,恢复速度较纯 AOF 快
性能优先(如缓存场景) RDB(或禁用持久化) 减少磁盘 IO 开销,缓存数据可从数据库重建
灾备需求 RDB 定期备份 + AOF 实时记录 RDB 用于全量恢复,AOF 用于增量数据补充

5. 高可用方案(主从复制与哨兵)

5.1 主从复制

  • 作用:实现数据备份与读写分离,主库(Master)负责写操作,从库(Slave)同步主库数据并提供读服务。
  • 原理
    • 全量复制:从库首次连接主库时,主库生成 RDB 快照发送给从库,从库加载快照后,主库再发送缓冲的增量命令;
    • 增量复制 :后续主库将写命令记录到repl_backlog_buffer,从库通过偏移量(offset)同步增量命令。
  • 配置 :从库配置slaveof <master-ip> <master-port>,主库无需额外配置。
  • 应用:读写分离(主库写、从库读),如电商商品详情查询走从库,减轻主库压力。

5.2 哨兵(Sentinel)

  • 作用 :监控主从节点状态,实现自动故障转移(主库挂了后从库自动升级为主库)。
  • 核心功能
    • 监控:定期检查主从节点是否存活;
    • 通知:通过 API 向管理员或其他应用发送故障通知;
    • 自动故障转移:主库故障时,选举从库升级为主库,其他从库重新指向新主库。
  • 部署:通常部署 3 个哨兵节点(奇数,避免脑裂),配置文件指定监控的主库信息。
  • 示例:一主二从 + 三哨兵架构,主库挂了后,哨兵通过投票选举其中一个从库升级为主库,客户端通过哨兵获取新主库地址继续访问。

6. Redis Cluster(分布式集群)

6.1 核心概念

  • 分片存储:将数据按 "槽位"(共 16384 个槽)分配到多个节点,每个节点负责一部分槽位(如 3 主节点各负责 5461 个槽);
  • 主从复制:每个主节点可配置从节点,实现数据备份与故障转移;
  • 去中心化:无中心节点,客户端直接与槽位对应节点通信,节点间通过 Gossip 协议交换状态。

6.2 数据路由

  • 槽位计算 :客户端根据CRC16(key) % 16384计算 key 所属槽位;
  • 重定向 :若客户端连接的节点不负责目标槽位,返回MOVED错误,指引客户端连接正确节点。

6.3 应用场景

  • 海量数据存储:突破单机内存限制,如存储 100GB 数据,可通过 3 主 3 从集群(每主节点 30GB + 内存)分片存储;
  • 高并发访问:多节点分担读写压力,提升整体吞吐量。

7. 性能优化实践

7.1 键设计规范

  • 命名规范 :用冒号分隔命名空间,如user:1001:infoorder:202508:list,避免键名混乱;
  • 避免大键:单个 key 存储数据不超过 10KB(如大 List、大 Hash 拆分存储),防止操作阻塞 Redis;
  • 过期键清理 :对缓存数据设置合理过期时间(EX/PX),避免内存溢出。

7.2 内存淘汰策略

当内存达到maxmemory限制时,Redis 通过以下策略淘汰键(配置maxmemory-policy

策略名称 说明(优先级从高到低)
volatile-lru 从设置过期时间的键中,淘汰最近最少使用的键
allkeys-lru 从所有键中,淘汰最近最少使用的键
volatile-ttl 从设置过期时间的键中,淘汰剩余时间最短的键
noeviction 不淘汰键,写操作返回错误(默认,不推荐生产环境)

推荐配置 :缓存场景用allkeys-lru(优先淘汰冷数据),业务数据用volatile-lru(仅淘汰过期缓存)。

7.3 命令与网络优化

  • 批量操作 :用MSET/MGET(String)、HMSET/HMGET(Hash)替代循环单条命令,减少网络往返;
  • Pipeline:客户端将多个命令打包发送,Redis 批量执行后返回结果,适合大量小命令场景(如批量更新库存);
  • 避免阻塞命令 :禁用KEYS *(遍历所有键,阻塞 Redis),改用SCAN(迭代遍历);避免HGETALL(大 Hash 全量获取),改用HMGET指定字段。

8. 总结

Redis 凭借丰富的数据结构高性能持久化分布式支持等特性,成为缓存、数据库、消息队列等场景的首选工具。核心知识点包括:

  • 数据类型:String(缓存、计数器)、Hash(对象存储)、List(队列)、Set(集合运算)、ZSet(排行榜)等,需结合场景选择合适类型;
  • 持久化:RDB(性能优先)与 AOF(安全优先),生产环境推荐混合持久化;
  • 高可用:主从复制(读写分离)+ 哨兵(故障转移);
  • 分布式:Redis Cluster 实现分片存储,突破单机限制。

通过合理设计键结构、优化命令、配置持久化与高可用策略,可充分发挥 Redis 性能,支撑高并发业务场景。

相关推荐
千层冷面1 小时前
Flask ORM 查询详解:Model.query vs db.session.query vs db.session.execute
数据库·python·django·flask
Navicat中国1 小时前
Navicat 询问 AI | 如何转换 SQL 为另一种数据库类型
数据库·人工智能·sql·数据库开发·navicat
Runing_WoNiu2 小时前
Redis核心架构
数据库·redis·架构
夜影风2 小时前
Nginx反向代理与缓存实现
运维·nginx·缓存
nbsaas-boot2 小时前
用 FreeMarker 动态构造 SQL 实现数据透视分析
数据库·windows·sql·freemarker·数据报表
电商API_180079052472 小时前
大规模调用淘宝商品详情 API 的分布式请求调度实践
服务器·数据库·分布式·爬虫
Menior_3 小时前
【补充】数据库中有关系统编码和校验规则的简述
数据库·mysql·oracle
晴子呀4 小时前
分库分表和sql的进阶用法总结
数据库·sql