大厂报价查询体系性能优化之道!

打印 上一主题 下一主题

主题 866|帖子 866|积分 2598

0 前言

机票查询体系,日均亿级流量,要求高吞吐,低延迟架构设计。提升缓存的效率以及实时盘算模块长尾延迟,成为制约机票查询体系性能关键。本文先容机票查询体系在缓存和实时盘算两个范畴的架构提升。
1 机票搜索服务概述

1.1 机票搜索的业务特点

机票搜索业务:输入目的地,然后点击搜索,背景就开始卷了。基本1~2s将最优结果反给用户。这个业务存在以下业务特点。
1.1.1 高流量、低延时、高成功率

超高流量,同时,对搜索结果要求也很高——成功率要高,不能查询失败或强说成功,希望能反给用户最优最新数据。
1.1.2 多引擎聚合,SLA不一

机票搜索数据来源哪?很大一部分来源自己的机票运价引擎。为补充产品丰富性,还引入国际一些GDS、SLA,如联航。将外部引擎和自己引擎结果聚合后发给用户。
1.1.3 盘算麋集&IO麋集

大家可能意识到,我说到我们自己的引擎就是基于一些运价的数据、仓位的数据,还有其他一些航班的信息,我们会盘算、比对、聚合,这是一个非常技术密盘算麋集型的这么一个服务。同时呢,外部的GDS提供的查询接口或者查询引擎,对我们来说又是一个IO麋集型的子体系。我们的搜索服务要将这两种不同的引擎结果很好地聚合起来。
1.1.4 不同业务场景的搜索结果不同要求

作为OTA巨头,还支持不同应用场景。如同样北京飞上海,由于搜索条件或搜索渠道不一,返回结果有所不同。如客户是弟子,可能搜到弟子特价票,其他用户就看不到。
2 公司基建

为应对云云业务,有哪些利器?
2.1 三个独立IDC

互相做灾备,实现此中一个IDC完全宕机,业务也不受影响。
2.2 DataCenter技术栈

SpringCloud+K8s+云服务(海外),感谢Netflix开源支撑国内互联网极速发展。
2.3 基于开源的DevOps

我们基于开源做了整套的DevOps工具和框架。
2.4 多种存储方案

公司内部有比力完善可用度比力高的存储方案,包罗MySQL,Redis,MangoDB……
2.5 网络可靠性

注重网络可靠性,做了很多DR开发,SRE实践,广泛推动熔断,限流等,以保证用户得到高质量服务。
3 机票搜索服务架构

3.1 架构图


IDC有三个,先引入GateWay分流前端服务,前端服务通过服务治理,和后端聚合服务交互。聚合服务再调用很多引擎服务。
聚合服务结果,通过Kafka推到AI数据平台,做大数据分析、流量回放等数据操作。云上部署数据的过滤服务,使传回数据淘汰90%。
4 缓存架构

4.1 缓存的挑战和计谋

4.1.1 为啥大量使用缓存应对流量高峰?

提高效率、速度的首选技术手段。
虽使用很多开源技术,但还有瓶颈。如数据库是分片、高可用的MySQL,但和一些云存储、云数据库比,其带宽、存储量、可用性有差距,通常需用缓存保护我们的数据库,不然频仍读取会使数据库很快超载。
很多外部依赖,提供给我们的带宽,QPS有限。而公司整体业务量是快速增长的,而外部的业务同伴给我们的带宽,要么已达技术瓶颈,要么开始收高费用。此时,使用缓存就可保护外部的一些合作同伴,不至于击穿他们的体系,也可帮我们降本。
4.1.2 当地缓存 VS 分布式缓存

整个架构的演进过程,一开始当地缓存较多,厥后部分用到分布式缓存。
当地缓存的主要题目:

  • 启动时,有个冷启动过程,对快速部署不利
  • 与分布式缓存相比,当地缓存命中率太低
对海量的数据而言,单机提供命中率非常低,5%乃至更低。对此,现已全面切向Redis分布式缓存。本着对战failure的理念,不得不思量失败场景。万一集群挂掉或一部分分片挂掉,这时需要通过限流客户端、熔断等,防止雪崩效应。
4.1.3 TTL


  • 命中率
  • 奇怪度
  • 动态更新
TTL生命周期跟业务强相关。买机票常常碰到:刚在报价列表页看到一个低价机票,点进报价详情页就没了,why?航空公司低价舱位票,一次可能只放几张,若在热门航线,可能同时几百人在查,它们都可能看到这几张票,它就会出现在缓存里。若已有10人订了票,其他人看到缓存再点进去,运价就已失效。对此,就要求权衡,不能单方面追求高命中率,还得兼顾数据奇怪度。为保证奇怪度、数据准确性,还有大量定时任务去做更新和清理。
4.2 缓存架构演进

4.2.1 多级缓存

架构图的三处缓存:

  • 引擎级缓存
  • L1分布式聚合缓存,基本上就是用户看到的终极查询结果
  • L2二级缓存,分布式的子引擎结果
若聚合服务需多个返回结果,很大程度都是先读一级缓存,一级缓存没有命中的话,再从二级缓存里面去读中心结果,这样可以快速聚合出一个大家所需要的结果返回。
4.2.2 引擎缓存

引擎缓存:

  • 查询结果缓存
  • 中心产品缓存
  • 基础数据缓存
使用一个多级缓存模式。如下图,最顶部是指引前的结果缓存,储存在Redis,引擎内部根据产品、供应商,有多个渠道的中心结果,所以对子引擎来说会有个中心缓存。

这些中心结果盘算,需要数据,这数据就来自最基础的一级缓存。

4.2.3 基于Redis的一级缓存

Pros:

  • 读写性能高
  • 水平扩展
Cons:

  • 固定TTL
  • 命中率和奇怪度的平衡
结果:

  • 命中率 ROI,削峰
8 Q&A

Q:啥场景用缓存?
A:所有场景都要思量缓存。高流量时,每级缓存都能带来很好的保护体系,提高性能的结果,但要思量到缓存失效的应对措施。
Q:缓存迭代过程咋样的?
A:先有L1,又加L2,主要因为流量越来越大,引擎外部依赖渐渐撑不住,不得不把中心结果也高效缓存,此即L1到L2的演进。二级缓存用Redis替换MongoDB,是出于高可用思量,费用节省也是一个因素,但更主要是发现自运维的MongoDB比Redis,整体可用性要差很多,所以最后决定切换。
Q:分布式缓存的设计方式?
A:分布式缓存的关键在于它的KV怎么设定?须根据业务场景,如有的KV里加入IP地址,即Pooling,基于Redis创建了它的队列,所以我们queue当中是把这种哀求方的IP作为创建的一部分放了进去,就能保证子任务能知道到哪查询它相应的返回结果。
Q:为什么redis的读写延迟能做到3ms以内呢?
A:读写延时低其实主要指读延时,读延时3ms内没题目。
Q:这队列是内存队列?还是MQ?
A:互联队列用Redis,主要是为保证其高可用性。
Q:缓存失效咋革新,涉及分布式锁?
A:文章所提缓存失效,并非指它里边存的数据失效,主要指整个缓存机制失效。无需分布式锁,因为都是单独的KV存储。
Q:缓存数据同等性咋保证?
A:非常难保证,常用本领:缓存超过阈值,强行清除。然后若有更精确内容进来,要动态革新。如本可存5min,但第2min有位用户查询并下单,这时肯定是要做一次实时查询,趁便把还没过期的内容也革新一遍。
Q:热key,大key咋监控?
A:对我们热区没那么明显,因为一般我们的一个key对应一个点,一个出发地和一个目的地,中心再加上各种渠道引擎的限制。而不像分片,你分成16或32片,可能某一分片逻辑设计不合理,导致那片过热,然后相应硬件直接到瓶颈。
Q:详解Pooling?
A:原理:子任务耗时间不一,若完全基于SOA举行动态随机分,肯定有的盘算节点分到的子任务较重,有的较轻,加入Pooling,就好像加入一个排队计谋,特殊是对中心还会实时调用离开几s的case,排队计谋能极大节省盘算资源。
Q:监控咋做的?
A:基于原来用了时序数据库,如ClickHouse,和Grafana,然后现在兼容Promeneus的数据收集和API。
Q:二级缓存采用Redis的啥数据类型?
A:二级缓存存储中心结果,应该是分类型的数据类型。
Q;TTL盘算应该思量啥?
A:最畏惧数据异常,如体系总返回用户一个已过期低票价,用户体验很差,所以这方面牺牲命中率,然后缩短TTL,只不过TTL控制在5min内,偶然还要微调,所以还得用机器学习模型。
Q:IP直连和Pooling没明白,是AGG中涉及到的盘算举行拆分,将中心结果举行存储,其他哀求里若也需要这中心盘算,可直接获取吗?
A:IP直连和PoolingIP直连,其实把负载均匀分到各节点Pooling,只不过你要盘算的子任务入队,然后每个运算节点每次取一个,盘算完再放回去,这样盘算效率更高。中心结果没有共享,中心结果存回是因为有的子任务需要中心离开,再去查其他实时体系,所以就相当于把它分成两个运算子任务,中心的任务要重回队列。
Q:下单雷同秒杀,发现一刹时票抢光了,相应缓存咋更新?
A:若有第1个用户选择了一个运价,没通过,要把缓存数据都给杀掉,然后尽量防止第2个用户还会陷入同样题目。
Q:多级缓存数据咋保证同等?
A:因为我们一级缓存存的是终极的结果,二级缓存是中心结果,所以不需要保持同等。
Q:一级、二级、三级缓存,哀求过来,咋提高吞吐量,按理说,每个查询过程都消耗时间,吞吐量应该下降?
A:是的,若无这些缓存,几乎所有都要走一遍。实时盘算,时间长,而且部署的集群能响应的数很有限,然后一、二、三级每级都能拦截很多哀求。一级约拦截20%,二级差不多40%~50%。此时同样的集群,吞吐量显然明显增加。
Q:怎样防止缓存过期时刻产生的击穿题目,目前公司是定时任务主动缓存,还是根据用户哀求举行被动的缓存?
A:对于缓存清除,我们既有定时任务,也有被动的更新。比如说用户又取了一次或者购票失败这些情况,我们都是会革新或者清除缓存的。
Q:搜索结果会根据用户特征重新盘算运价和票种吗?
A:为啥我的运价跟别人不同等,是不是被大数据杀熟?其实不是的,那为啥同样查询返回结果不一呢?有一定比例是因为缓存数据异常,如前面缓存的到反面票卖光了,然后又推给了不幸用户。公司有很多引擎如说国外供应商,尤其联航,他们体系带宽不敷,可用性不高,延时也高,所以部分这种低价票不能及时返回到我们的最闭幕果,就会出现这种“杀熟”,这并非算法故意,只是体系局限性。
Q:Pooling 为啥用 Redis?
A:为追求更高读写速度,其他中心件如内存队列,很难用在分布式调度。若用message queue,由于它存在明显顺序性,不能基于KV去读到你所写的,如你发了个子任务,这时你要定时取其结果,但你基于MQ或内存队列没法拿到,这也是一个限制。
Q:多级缓存预热咋保证MySQL不崩?
A:冷启动题目更多作用在当地缓存,因为当地缓存发布有其他的情况,需要预热,在这之间不能接受生产流量。对多级缓存、分布式缓存,预热不是题目,因为它本就是分布式的,可能有部分节点要下线之类,但对整个缓存机制影响很小,然后这一部分哀求又分散到我们的多个服务器,不会产生太大抖动。但若整个缓存机制失效如缓存集群完全下掉,还是要通过熔断或限流对实时体系作过载保护。
Q:Redis对聚集类QPS不高,咋办?
A:Redis多加些节点,淘汰它的存储使用率,把整体throughput提上即可。若你对云业务有了解,就知道每个节点都有throughput限制。若单节点throughput成为瓶颈,那就降低节点使用率。
关注我,紧跟本系列专栏文章,咱们下篇再续!
作者简介:魔都技术专家兼架构,多家大厂后端一线研发经验,各大技术社区头部专家博主,编程严选网创始人。具有丰富的引领团队经验,深厚业务架构和解决方案的积聚。
负责:

  • 中央/分销预订体系性能优化
  • 活动&优惠券等营销中台创建
  • 交易平台及数据中台等架构和开发设计
目前主攻降低软件复杂性设计、构建高可用体系方向。
参考:
本文由博客一文多发平台 OpenWrite 发布!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

花瓣小跑

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表