一、事务与批量操作¶
1.1 简介¶
Redis 事务的特性
-
redis的事务只是保证了多条命令的串行执行
-
并不能保证执行命令的原子性
-
redis事务只有在入队异常的时候会回滚,进入server执行并不会回滚
1.2 常用命令¶
显式开启Redis事务命令 MULTI
MULTI
EXEC提交事务,执行队列命令
EXEC
DISCARD 清除事务中的commands队列,并恢复连接状态;
DISCARD
watch 给事务一个执行条件
WATCH
清除事务的执行条件
UNWATCH
补充说明:
-
MULTI 开启后,后续命令先入队,直到 EXEC 才真正执行。
-
Redis 事务保证的是“队列中的命令串行执行”,不是关系型数据库那种失败即回滚的强事务。
-
WATCH 的作用更接近乐观锁:当被监视的 key 在 EXEC 前发生变化时,事务会放弃执行。
转账示例
local:1>set a 100
"OK"
local:1>set b 100
"OK"
local:1>multi
"OK"
local:1>incrby a 10
"QUEUED"
local:1>decrby b 10
"QUEUED"
local:1>exec
1) "OK"
2) "110"
3) "OK"
4) "90"
事务失败示例,事务不能保证原子性
local:1>set t1 t1
"OK"
local:1>set t2 10
"OK"
local:1>multi
"OK"
local:1>incrby t1 1
"QUEUED"
local:1>incrby t2 1
"QUEUED"
local:1>exec
1) "OK"
1) "ERR value is not an integer or out of range"
1) "OK"
1) "11"
1) "OK"
local:1>get t1
"t1"
local:1>get t2
"11"
带watch 监控的事务
local:1>watch t1 # 监控t1
"OK"
local:1>set t1 10 # 改变t1
"OK"
local:1>multi
"OK"
local:1>set t2 10
"QUEUED"
local:1>exec
local:1>get t2
"11"
local:1>get t1
"10"
补充说明:
-
在事务开启后,客户端通常会进入
(TX)状态,表示后续命令只是入队,还没有真正执行。 -
如果 WATCH 监控的 key 在 EXEC 前被修改,
EXEC会返回(nil),表示整个事务队列被放弃执行。 -
这里更准确地说是“事务未执行”,而不是像关系型数据库那样“执行后回滚”。

视频补充:事务实践中的两个重点
-
如果命令在入队阶段就有语法问题,事务会直接失败;但如果是执行阶段出现类型错误,其他命令仍可能继续执行,不会整体回滚。
-
WATCH + MULTI + EXEC 常用来实现带条件的更新,例如扣减库存、账户转账等场景中的并发控制。
二、订阅与发布¶
2.1 简介¶
什么是发布订阅?
Redis支持发布-订阅(Pub/Sub )模式,它允许消息的发布者将消息发送给订阅者,实现了一对多的消息 传递机制。Redis订阅与发布的参与者有以下三个:
-
发布者(Publisher):发布者是发送消息的一方。它使用 PUBLISH 命令将消息发送到指定的频道 (Channel)。一个发布者可以向多个频道发布消息。
-
频道(Channel):频道是消息的目标地址。订阅者通过订阅指定的频道来接收发布者发送的消息。 频道由字符串表示,可以使用任意字符串作为频道名。
-
订阅者(Subscriber):订阅者是接收消息的一方。它使用 SUBSCRIBE命令来订阅一个或多个频道, 然后等待接收发布者发送的消息。一个订阅者可以同时订阅多个频道。
2.2 常用命令¶
订阅,我们打开一个客户端先订阅一个频道channel1
local:1>subscribe channel1
Switch to Pub/Sub mode.
Close console tab to stop listen for messages.
1) "subscribe"
1) "channel1"
1) "1"
我们再起一个客户端,给频道channel1发送消息hi
local:1>publish channel1 hi
"1"
我们看第一个客户端发现多了以下消息
1) "message"
1) "channel1"
1) "hi"
2.3 实现¶

视频补充:Pub/Sub 内部实现思路
-
Redis 会把频道维护在哈希表
server.pubsub_channels中,key 是频道名,value 是订阅该频道的客户端链表。 -
当客户端执行 SUBSCRIBE 时,Redis 会先查找频道是否存在:
- 如果频道已存在,就把当前客户端挂到该频道对应的订阅链表中。
-
如果频道不存在,就先创建频道,再把客户端加进去。
-
当发布者执行 PUBLISH 时,Redis 会根据频道名找到对应链表,并一次性遍历所有订阅者进行消息投递。
-
这也意味着 Pub/Sub 更偏向实时广播,消息默认不做持久化,也不保证离线重投;如果业务需要可追溯和可靠消费,通常要结合 Stream 或专业 MQ 来做。