Redis 7 的新数据结构:Stream 和 Function 实战
David Ng | 2026-09-14T14:27:00 | Database
Redis 7 引入的 Stream 和 Function 终于在生产中用上了。Stream 做消息队列比 List 靠谱多了,Function 让服务端脚本更优雅。
Redis 7 出了有一段时间了,但很多团队还在用 String + List + Hash 老三样。最近在项目里用上了 Stream 和 Function,体验比预期好很多。 ## Redis Stream 做消息队列 以前用 Redis 做消息队列,通常是 List + LPUSH/BRPOP。但 List 有几个硬伤: - 消息消费后就没了,不能重新消费 - 没有消费者组的概念,多个消费者会重复消费 - 没有 ACK 机制,消费者挂了消息就丢了 Stream 完美解决了这些问题: ```bash # 生产者:添加消息 XADD orders * user_id 123 product_id 456 amount 99.9 # 创建消费者组 XGROUP CREATE orders order-processors $ MKSTREAM # 消费者 1:读取消息 XREADGROUP GROUP order-processors consumer-1 COUNT 10 BLOCK 5000 STREAMS orders > # 确认消费完成 XACK orders order-processors 1695123456789-0 # 查看未确认的消息(消费者挂了可以重新处理) XPENDING orders order-processors ``` 关键特性: - **消费者组**:多个消费者自动负载均衡,每条消息只被一个消费者处理 - **ACK 机制**:消息处理完才确认,消费者挂了可以重新分配 - **持久化**:消息不会因为消费就消失,可以设置最大长度自动裁剪 - **历史回溯**:可以从任意位置开始消费 在我们的场景下(订单处理队列),Stream 比之前的 List 方案可靠多了。之前偶尔会丢消息,用 Stream 之后再没出现过。 ## Redis Function 以前在 Redis 里执行复杂逻辑用 EVAL + Lua 脚本,但有几个问题: - 每次调用都要发送完整的 Lua 代码 - 代码管理困难(Lua 脚本散落在各个服务里) - 没有版本管理 Function 让这一切更优雅了: ```lua -- 注册函数(只需要执行一次) redis.register_function('check_and_deduct', function(keys, args) local stock = redis.call('GET', keys[1]) if stock == nil then return -1 end stock = tonumber(stock) local amount = tonumber(args[1]) if stock < amount then return 0 end redis.call('DECRBY', keys[1], amount) return 1 end) ``` ```bash # 调用函数(简洁!) FCALL check_and_deduct 1 product:123:stock 5 ``` 函数注册后持久化在 Redis 里,重启也不会丢。可以用 FUNCTION LIST 查看所有注册的函数,用 FUNCTION DUMP/RESTORE 备份和迁移。 ## 总结 - 如果你在用 Redis List 做消息队列 → 换成 Stream - 如果你有复杂的 Lua 脚本散落在各处 → 用 Function 统一管理 - 这两个特性都是向后兼容的,不影响现有功能