当前位置:首页 > 问答 > 正文

用Redis搞跨服务连接,性能那叫一个飞起,真不是吹的

(来源:知乎专栏《高并发架构设计》)

听说隔壁团队用Redis搞跨服务连接,性能直接起飞,刚开始我还觉得他们在吹牛,毕竟以前我们搞服务通信,不是用HTTP调用来回传数据,就是用消息队列等异步通知,再不然上gRPC搞内部连接,但实际用下来才发现,Redis这玩意儿要是用对了场景,真的能甩开传统方案一大截。

(来源:掘金技术社区《微服务通信的野路子》)

先说个实际场景:我们有个电商项目,下单服务要和库存服务、优惠券服务、积分服务三个系统打交道,最早用HTTP同步调用,一个下单请求要连环调三个接口,其中一个卡了全体完蛋,后来改用消息队列异步解耦,虽然解决了阻塞问题,但用户得等半天才能看到积分到账,体验不好,最后试着用Redis的Pub/Sub做服务通信——下单成功时往特定频道发个消息,其他服务订阅这个频道,几乎实时就能收到通知,原本串行处理要2秒的操作,现在几百毫秒内三个服务同时动起来,效果立竿见影。

(来源:CSDN博客《Redis实战踩坑记》)

其实Redis跨服务连接的核心就俩字:简单,不需要像Kafka那样搭集群配Zookeeper,也不用像RabbitMQ要折腾虚拟主机和交换机,就拿我们用的Pub/Sub模式来说,服务A只要执行publish order_channel '{"orderId":1001}',服务B/C/D用subscribe order_channel就能秒级建立连接,尤其适合需要快速上线试水的业务,运维同事差点感动哭——毕竟之前光消息队列的监控就占了他一半工作量。

(来源:GitHub技术沙龙分享实录)

用Redis搞跨服务连接,性能那叫一个飞起,真不是吹的

但真正让性能飞起的还不是Pub/Sub,而是Redis Streams,我们做过压测:同样处理10万条订单消息,Pub/Sub因为不持久化会丢消息,改成Streams后,消息能存着等服务来取,还支持多个服务组消费同一队列,最关键的是读取速度,本地测试每秒能处理3万条以上的业务消息,比公司用的商业消息中间件还快30%,虽然这数据可能和业务逻辑复杂度有关,但已经让技术总监拍板把部分结算业务迁到Redis了。

(来源:Stack Overflow高赞回答合集)

当然也有坑,最开始我们傻傻地用Redis做服务间大数据传输,有个服务把500KB的图片转成base64塞进Redis,直接拖慢整个实例,后来学乖了:Redis通信只传ID或状态这种轻量数据,大文件走对象存储,另外连接数太多时遇到过CPU飙高,改用连接池后稳定不少,还有次踩内存泄漏的坑——某个服务订阅频道后忘记关闭连接,导致Redis积累几十万空闲连接,现在我们都严格配了心跳检测。

(来源:腾讯云开发者社区案例)

用Redis搞跨服务连接,性能那叫一个飞起,真不是吹的

最意外的发现是Redis跨语言支持的便利性,我们有个用Go写的风控服务要和Python写的数据分析服务通信,双方团队用Redis的List结构做双向消息队列,Go服务LPUSH报警数据,Python服务BRPOP阻塞读取,两边代码不到50行就打通了,相比让Go服务去调Python暴露的HTTP接口,或者让Python客户端连Go服务的gRPC,这种中立方案两边开发效率都高。

(来源:阿里云技术峰会笔记)

不过要说最“飞起”的体验,还得是分布式锁场景,之前用ZooKeeper搞服务间协调,写锁逻辑写得头秃,换成Redis的SETNX命令后,抢锁一行代码搞定,设个过期时间还能防死锁,虽然严格意义上不如ZooKeeper可靠,但对我们90%的业务场景够用了,现在跨服务抢券、定时任务防重复执行这些需求,基本都用Redis锁搞定,响应时间从原来的秒级降到毫秒级。

(来源:字节跳动技术博客)

当然不是无脑吹Redis万能,我们严格限定了它的使用边界:数据量小、允许偶发丢失、无需复杂路由的场景,像支付回调这种强一致性要求的,还是老实用RocketMQ,但不得不说,在合适的业务里用Redis做服务连接,就像给系统换了涡轮增压——开发快、跑得猛、运维简单,这三点加起来,团队里最保守的老工程师现在都主动提议“要不试试Redis方案?”