测试PUBLISH和SUBSCRIBE能不能被排进MULTI事务,再验证一个连接真正进入订阅模式之后,普通读写命令会不会被拒绝,划清事务排队和真正订阅态这两条完全不同的边界。
Pub/Sub和事务是两套听起来不太搭的机制,测测能不能混用。
代码cmd(s, "MULTI") cmd(s, "PUBLISH", "ch1", "hello") cmd(s, "SET", "pxkey", "1") cmd(s, "EXEC") -- 另一个连接 cmd(s2, "MULTI") cmd(s2, "SUBSCRIBE", "ch2") cmd(s2, "EXEC")
这一步比预想的更宽松。
结果PUBLISH排队: +QUEUED EXEC: [:0, +OK] (:0表示没有订阅者收到这条消息,SET成功) SUBSCRIBE排队: +QUEUED EXEC: [ [subscribe, ch2, 1] ] (是订阅确认消息本身,作为EXEC数组的一个元素)
验证了两点:PUBLISH跟其它命令一样,只是排队等EXEC统一执行,返回值(:0,表示没有人订阅ch1)也正常出现在数组里;更意外的是SUBSCRIBE本身居然也能被排进事务——EXEC执行完,这个连接就进入了订阅ch2的状态,EXEC返回的数组里那个元素就是的订阅确认消息本身。
跟上一步"SUBSCRIBE能被排进事务"不同,这里说的是真的执行了SUBSCRIBE之后的连接状态。
结果SUBSCRIBE ch3 → 订阅确认消息 GET pxkey (订阅状态下尝试发普通命令) → 报错: ERR Can't execute 'get': only (P|S)SUBSCRIBE / (P|S)UNSUBSCRIBE / PING / QUIT / RESET are allowed in this context PING (订阅状态下) → 正常返回pong
每一步都是本文上面用裸RESP协议跑出来的原始结果。