Skip to content

Redis

约 1683 个字 9 行代码 1 张图片 预计阅读时间 6 分钟

简介

Redis(Remote Dictionary Server)是一个 key-value 的数据库,常用于缓存、消息队列、会话存储等场景。需要注意正常情况下 Redis 是存储在内存的。本地安装自然是推荐使用 docker 拉取:

docker pull redis:latest
docker run -d --name redis -p 6379:6379 redis

配置

Redis 配置文件位于 Redis 安装目录下,文件名为redis.conf,Redis 默认不以守护进程的方式运行。

守护进程是一种在后台运行的特殊进程,它独立于控制终端,并且通常不与用户进行直接的交互。它的主要目的是在系统启动时就开始运行,在后台持续地执行一些系统级或网络级的任务,等待特定事件的发生并对其进行处理。

数据类型

  1. 字符串:string 类型是二进制安全的,理论上可以存储任意类型,常存储字符串、整数或者浮点数,一个键最多存储 5112 MB
  2. 哈希:hash 本身也是一个 string 类型的 key-value 结构,特别适合于存储对象
  3. 列表:List 是简单的字符串列表,按照插入顺序,可以将一个元素添加到头部或者尾部
  4. 集合:Set 是 string 类型无序集合
  5. 有序集合:Zset 和 Set 的区别是每个元素都会关联一个 double 类型分数,将按照这个分数排序

指令

连接

连接到本地redis服务

redis-cli

连接到远程redis服务器

redis-cli -h host -p port -a password

键值操作

设置键值对

SET key val

删除键值对

DEL key

检查键是否存在

EXISTS key

给key设定过期时间,以秒计数

EXPIRE key seconds

返回过期时间

TTL key

配置

键空间通知

当Redis中的某个Key过期时,Redis可以发布一个消息,后端程序订阅这个消息并执行逻辑。Redis默认为了节省CPU性能,是关闭事件通知功能的。需要修改配置文件redis.conf,在redis.conf中修改:

notify-keyspace-events "Ex"
  • E:表示键事件通知(Keyevent events),即以事件名为频道。
  • x:表示过期事件(Expired events)。

在使用docker部署时推荐在拉取时指定配置

用例

实际开发中当然是使用相应的库与Redis交互

缓存

JWT(JSON Web Token)采用无状态验证机制,服务端不存储会话信息,令牌的合法性完全取决于签名及其有效期。这种设计虽然提升了系统的可扩展性,但也带来了显著缺陷:令牌一旦签发,在其有效期内无法被服务端主动撤回。在用户修改密码、账号注销或检测到非法登录等关键安全场景下,无法即时阻断已签发令牌的访问权限,存在安全风险。

为了弥补 JWT 无法主动失效的短板,引入 Redis 作为分布式缓存层,构建令牌黑名单系统:

  • 失效触发:当用户执行登出或敏感操作时,后端将该 JWT 的唯一标识(如 jti 载荷)存入 Redis 黑名单。
  • 生存时间控制 (TTL):黑名单记录的过期时间设置为该 JWT 的剩余有效时长。利用 Redis 的 TTL 机制,确保令牌在自然过期后自动移出黑名单,避免内存冗余。
  • 校验解耦:在后端校验中间件中,增加“黑名单检索”环节。系统在完成 JWT 签名验证后,需同步确认该令牌是否存在于 Redis 黑名单中。

消息队列

List

这是最简单的“点对点”模式。

  • 优点
  • 极其简单:只需 LPUSHBRPOP 指令
  • 低延迟:Redis 内存操作,性能极高。
  • 支持阻塞读取:BRPOP 可以让消费者挂起,不占用 CPU 轮询。
  • 缺点
  • 不支持多播:一条消息只能被一个消费者“抢”走。
  • 消息丢失风险:消息一旦弹出(Pop),如果消费者在处理过程中崩溃,该消息就永久丢失了。
  • 适用场景:简单的异步处理,如发送短信验证码、后台导出小文件。

Pub/Sub

这是一种“广播”模式。

  • 优点
  • 支持多播:一个生产者发布,无数个订阅者都能实时收到。
  • 解耦性强:生产者完全不需要知道谁在订阅。
  • 缺点
  • 消息不持久化:这是最大的硬伤。如果订阅者网络断开或服务重启,离线期间的消息会全部丢失。
  • 无回溯能力:无法查看历史消息。
  • 适用场景:对消息丢失不敏感的实时场景,如即时聊天室、配置更新推送、实时弹幕。

Stream (流)

这是Redis 5.0以后推出的“专业级”方案,设计思路借鉴了 Kafka。

  • 优点
  • 持久化与回溯:消息像日志一样存储,即使消费者离线,上线后也能从上次的位置继续消费。
  • 消费组 (Consumer Group):支持多个消费者平摊工作量,提高处理能力。
  • 消息确认机制 (ACK):消费者处理完必须回复 ACK,否则消息会进入 Pending列表,支持故障恢复。

  • 缺点

  • 复杂度较高:API 相对复杂(如 XADD, XREADGROUP, XACK),需要管理消费组状态。
  • 内存占用:因为是持久化存储,消息堆积过多会消耗较多Redis内存(需要手动设置 MAXLEN 修剪)。
  • 适用场景:核心业务系统,如订单处理、支付通知、需要高可靠性的微服务通信。

会话存储

在单机时代,Session存储在服务器的内存中。当架构演进为分布式时,问题就出现了:

  1. 用户登录:请求落在了Server A。Server A 验证通过,在自己的内存里开辟了一块空间存下了User{ID: 1},并给浏览器发了一个SessionID=AAA 的Cookie。
  2. 用户操作:用户点击“我的订单”。负载均衡(如 Nginx)这次将请求分发到了Server B。
  3. 会话失效:Server B收到SessionID=AAA后,在自己的内存里翻找,发现查无此人。

结果:Server B 认为用户未登录,强制跳转到登录页面。用户会觉得系统反复闪退,体验极差。

解决思路是将会话数据从Web服务器中剥离,建立一个所有服务器都能访问到的“公共仓库”,这个公共仓库必须满足:极高的读写性能和支持过期自动清理。这正是 Redis 的强项:

  • 统一存储:不再存放在 Server A 或 B 的内存,而是存入 Redis 集群。
  • 状态共享:
  • Server A 写入 Session 后,数据物理上存在 Redis 里。
  • Server B 收到请求时,拿着 Session ID 去 Redis 里查。因为大家看的是同一个仓库,所以 B 能立刻认出用户。