不能直接用。Redis Pub/Sub无持久化、无ACK、不保证投递,无法支撑协同过滤所需的可靠兴趣更新;应采用“Pub/Sub触发+Stream持久化+ZSet存状态”的分层架构,确保实时性与一致性。

Redis Pub/Sub 能否支撑实时协同过滤推荐?
不能直接用。Redis 的 PUB/SUB 本身不存历史消息、无 ACK、不保证投递,一旦订阅者断连就丢数据——而协同过滤的用户兴趣点更新(比如“用户 A 刚对商品 X 打了高分”)必须可靠触达所有在线推荐服务节点,否则实时性与一致性全崩。
它只适合做「轻量广播信令」:比如通知各推荐模块「用户兴趣模型已更新,请从 hash 或 zset 里重新拉取最新向量」,而不是把原始行为事件当消息体发出去。
如何设计可靠的用户兴趣点更新链路?
用 PUB/SUB 做触发器 + 持久化存储做事实源,是唯一稳妥组合:
- 用户行为(点击/评分/停留)先写入
stream(如user:behavior:stream),带 ID 和时间戳,支持重放 - 一个常驻消费者组(
CONSUMER GROUP)从stream拉取、计算兴趣向量、写入zset user:A:interest(成员=物品ID,score=兴趣权重) - 该消费者在完成一次批量更新后,向频道
channel:interest:update发布一条极简消息:{"user_id":"A","version":12345} - 所有推荐服务实例都
SUBSCRIBE该频道;收到后立刻去查zset user:A:interest,比对本地缓存 version,不一致则全量同步
为什么不用 PUBLISH 直接发兴趣向量?
三个硬伤:
-
PUBLISH消息大小受限(默认 512MB,但实际网络和客户端缓冲会更早爆),用户兴趣zset动辄上千项,序列化后远超安全阈值 - 订阅者无法知道消息是否被处理成功——如果推荐服务在反序列化时出错,这个向量就永久丢失,且无从追溯
- 不同服务实例可能因网络抖动收到重复或乱序消息,而
PUB/SUB不提供去重/顺序保障,导致兴趣状态错乱
所以,真正承载数据的是 zset 或 hash,PUB/SUB 只传指针——这是关键分层。
实际部署要注意哪些坑?
几个真实踩过的点:
- 别用
PSUBSCRIBE做通配符监听(如channel:interest:*),高并发下 Redis 会退化为 O(N) 匹配,CPU 瞬间拉满;固定频道名 + 多SUBSCRIBE更稳 -
stream消费者组记得设MAXLEN ~1000000并启用~修剪,否则磁盘悄无声息吃光 - 推荐服务重启时,要先完成本地
zset同步,再执行SUBSCRIBE,否则可能漏掉刚发布的那条 update 消息 - 如果推荐服务有多个副本,每个副本必须用不同
GROUP名消费stream,否则互相争抢消息,导致部分副本永远收不到更新
最易被忽略的是:你写的「实时」,其实是「流式计算 + 原子状态读取 + 信令驱动」三段拼出来的——少一段,就不是实时,只是看起来快。


















