背景
目前公司社交应用“暖聊”中的首页推荐等用户匹配功能,都是基于 es 算法实现,那么就需要将用户数据实时同步到 es。项目中操作 es 的方式是基于 jpa 框架直连操作 es,当用户信息变更时,通过 jpa 的 save 方法实时同步用户数据到 es。这样做的后果就是,es 更新频繁,在用户活跃高峰期,es 服务器 IO、CPU 都面临巨大的压力,甚至会直接影响线上功能的正常使用,同步 es 的方式调整优化迫在眉睫。
现状
当前项目 es 集群配置:2核4G 2节点,线上日活 4w+,es 服务器 CPU 使用率在用户活跃时段基本处于 90% 以上。当公司通过投放或者各种营销方式成功引流时,线上将会迎来流量小高峰,es 服务器 CPU 使用率甚至可能达到 100%,导致项目中任何 es 请求都处于超时状态,服务出现短时间内不可用。
优化方案
优化方案必须满足两个条件
- 短时间内解决线上 es 服务不可用问题
- 彻底优化 es 同步方式,从根本上解放 es 服务器压力
基于此,我们做了两步优化,服务器升配和引入 Flink + Kafka + es 流式处理
-
提升硬件配置
为了及时改变线上服务不可用的现状,我们做了es 服务器配置的升级,从 2核4G 2节点 提升到 8核16G 3节点,从硬件层面提升 es 服务的并发处理能力。做完硬件层面的提升后,线上反馈很明显,基于当前应用的增长量,可以保证在短时间内不再有因 es 导致的服务不可用风险。
升配后的 es 集群表现:
-
基于 Kafka -> Flink -> es ,实现用户数据实时同步 es
- 为什么选择 Kafka -> Flink -> es 的流式处理
要想彻底解决 es 服务器压力问题,必须替换项目中基于 jpa 直连操作 es 的方式。新的替代方式需要至少满足下 2 个条件:
- 容错性:如果处理过程出现故障,要能够自行恢复,并且从它离开的位置再次开始处理;
- 高性能:延时应尽可能的小,吞吐量应尽可能的大(批量操作 es 可以有效提升 es 性能);
Flink 的 checkpoint 能很好的结合 Kafka 偏移量,保证程序的容错恢复以及程序启动时状态恢复。
在阿里,Flink集群能达到每秒处理17亿数据量,一天可处理上万亿条数据。并且 Flink 集成 es 提供批量处理的方式,可以大大减少访问 es 的次数。
使用 Flink sink 同步 es 还有个优点,可以很好的支持增量更新。只需要将涉及到的属性字段放入一个 map 中,在同步 es 时只会更新我们指定的字段,无需担心会将其他字段覆盖为空。
- 优化过程
第一步:统一项目中更新用户信息入口,通过 Kafka 消息将业务与 es 操作解耦。
第二步:接入 Flink 流处理框架。它可以在内存中对数据进行分布式计算,然后通过 sink 将数据输出到外部系统es。