实时系统一定要上Kafka吗?一支做加密货币行情的小团队用实际经验给出了不同的答案。
他们面临的需求很典型:每秒从交易所WebSocket接收3000到4000条实时价格更新,前端已经直连交易所获取超低延迟数据,但用户还需要一个能快速查询的REST接口——排序、筛选、分页、排行榜,这些功能WebSocket给不了。
最初他们用PostgreSQL,高频写入叠加排序查询,很快撑不住。团队不想为了"实时"二字就引入全套分布式基础设施,于是换了个思路:Redis做实时状态层,Lua脚本做计算。
数据流被简化成两条线。一边是ECS服务维持交易所WebSocket连接,把不同格式的行情数据统一成内部标准格式;另一边Redis直接支撑API查询——字符串存价格和payload,有序集合做排行榜。前端继续直连交易所拿流,后端专注解决"查"的问题。
这个架构的关键在于把"推送"和"查询"彻底分开。WebSocket负责前者,Redis负责后者,互不干扰。
但第一版实现走了弯路。团队最初用Python做大部分计算,把数据存成哈希结构,排行榜靠Python在内存里排序。问题很快暴露:Python的GIL让多线程成了摆设,单进程CPU打满,多进程又导致Redis连接数暴涨。更隐蔽的是内存碎片——频繁创建销毁小对象,RSS内存涨到8GB,服务被迫重启。
他们意识到,Redis不只是缓存,它的数据结构本身就是计算能力。把排序、筛选、聚合逻辑搬进Lua脚本,在Redis内部执行,网络往返和Python开销一起消失。
具体做法并不复杂。有序集合按价格、涨跌幅、交易量等维度维护多个排行榜,Lua脚本处理分页和过滤,原子操作保证一致性。原本Python里几十毫秒的排序,现在几毫秒在Redis内完成。
这个方案也有边界。Lua脚本单线程执行,复杂逻辑会阻塞其他命令;调试困难,出错信息有限;团队规模和Redis经验也是前提。作者坦承,如果查询模式更复杂,或者需要跨分片聚合,他们可能会走向不同的技术选型。
但他们的核心判断值得注意:很多"实时系统"的复杂度是自找的。Kafka、流处理器、事件总线——这些工具解决的是特定规模的问题,不是每个场景都需要。先理解自己的读写模式、延迟要求和团队能力,再决定架构厚度,往往比追技术潮流更务实。
最终这套系统跑了很长时间,4k updates/sec的吞吐,亚毫秒级查询延迟,基础设施只有Redis和几行Lua。不是最先进的方案,但是够用的方案。
热门跟贴