写点什么

国际酒店用户服务能力提升(二)

  • 2020-12-10
  • 本文字数:3752 字

    阅读完需:约 12 分钟

国际酒店用户服务能力提升(二)

本文承接《国际酒店用户服务能力提升(一)》中对 L-D 环节顺畅度的提升。上文中分析了顺畅度情况较差的原因,下文会详细说明我们究竟做了什么来提升顺畅度。


2. 售前服务


2.2 L-D 环节顺畅度提升


(2)报价抓取调度机制改造


③ 离线抓取方案设计


既然使用了缓存,并且存在缓存和真实库存情况不一致的问题,那么说明缓存中的数据不是最新的真实库存情况。这里我们定义了一个概念叫缓存报价的新鲜度,缓存新鲜度 = 缓存报价被使用时刻的时间-抓取回数时刻的时间,只要保证缓存足够新鲜,发生变价和房态变化的概率将会越低。而缓存的新鲜度受抓取的频次影响,抓取频次受两次抓取的时间间隔(下文统称 cache time)影响。


上文有提到在原有机制中 cache time 是由人工进行配置并且是不可靠的,脱离原有机制思考一下都有哪些因素会影响 cache time:


  1. 城市、酒店、日期的的热度不同(相对热门库存变化会更快);

  2. 代理商差异(qps 能力不同、覆盖的城市和酒店不同)。


基于上面的因素,可以在较冷门的报价上减少 qps 资源的投入,而让 qps 资源更多地向热门倾斜。


如何更合理地让 qps 资源向热门倾斜呢?热门其实对于搜索来说,说明用户的搜索频次越高。那么将更多的 qps 资源分配给搜索频次更多的报价就可以实现该目的。如下图,对于某一个 wrapper(针对一个代理商),将用户搜索过它所能覆盖的酒店以 酒店+入离店日期 的维度进行排序,能得到如下图的曲线。那么每一个最小维度应该分配的 qps = (最小维度的搜索量(count)/ 总搜索量(S))× qps 总量。qps 是每秒应该抓取报价的次数,cache time 是报价抓取的间隔,有了 qps 就能知道 cache time 应该是多少。



在这里我们并没有直接使用单纯的搜索量排序, 因为当天的搜索量在报价抓取的时刻是处于未来时刻的,我们使用的是通过历史数据对于未来流量的一种预测模型。参考算法模型在预测未来趋势时使用的趋势特征和实时特征:我们将过去 n 天的搜索量数据作为趋势特征,并且使用搜索日期和入店日期的相对日期来和实时日期进行拟合;将过去 1 天的搜索量数据作为实时特征。加权搜索量 = 过去 n 天搜索量 × 权重 1 + 过去 1 天搜索量 × 权重 2


计算 cache time 的时序图如下,其中 rank 指的是上文中的加权搜索量。


有了合理的 cache time 后,还需要一种机制能保证报价可以按照预想的 cache time 的进行更新。为此我们做了当报价缓存时间到达预设的 cache time 后进行更新的离线抓取能力,来保证 qps 资源能充分得到利用,报价的抓取间隔达到预期。至此,对于抓取调度的改造基本完成。整体 cache time 的闭环如下图所示:



抓取调度机制上线后并,负责报价回数存储缓存的系统线上机器 load 飚高,在使用新的抓取调度机制后 GC 严重。在排查问题后,为了解决问题我们对报价回数存储缓存的系统(rebuild 系统)进行了重构,下文将对这一过程进行说明。


(3)rebuild 系统重构



上文有展示过报价的简化结构,在原有的架构中这部分业务都是在 rebuild 系统中进行的。rebuild 系统提供的能力按照功能性分为几个部分:


  1. 处理报价回数:先处理 wrapper 维度的回数,再将 wrapper 维度报价与缓存中已有的酒店维度报价缓存更新整合并重新存储到缓存中;

  2. 计算最新的酒店维度最低价并用于酒店排序展示;

  3. 对于缓存中基础报价的过滤、包装、定价。


其中职能 1 和职能 2 部署在实体机集群上,职能 3 由于历史原因部署在虚拟机集群上,也就是说同样的一套代码分割成了两部分运行在两个性质完全不同的集群上。而出现问题的集群就是实体机集群。我们接着说明,为什么在抓取调度机制上线后,实体机集群会出现机器 load 飚高的问题。


酒店业务是同一个酒店会有多个 wrapper(代理商)同时售卖的。用户搜索一个酒店时,会触发一个酒店下所有能提供该酒店报价的代理商的报价抓取并将结果展示给用户。如下图。




在一次回数过程中,需要将之前存储的酒店维度报价缓存取出后,更新最新的 wrapper 维度报价,再重新存储。这其中就会有大量的序列化/反序列化、GC、IO、业务流程计算等带来的资源的消耗。流程如下图。



在原有流程中,普遍情况下都是由用户触发抓取和回数,大概率事件是同一个酒店下多个 wrapper 会同时发起抓取报价的请求并且可以在一定时间范围内完成回数。而为了避免对资源的消耗,之前的同事设计了一个回数等待的机制(上图流程 ②)。在一段时间内,会聚合统一酒店维度(酒店+入离店日期)的 wrapper 报价抓取结果,仅对缓存池中的酒店维度缓存报价进行一次读和写操作,这样就减少了对资源的消耗。而新的调度抓取机制并不是依赖用户的搜索触发,在上文介绍抓取调度机制时有提到,新的调度抓取机制会将抓取流量打散,根据抓取的最小粒度(wrapper+酒店+入离店日期)应有的 cache time 进行触发抓取,如下图所示。



原有的流程 ② 中减少机器消耗资源的能力对新的抓取调度机制不再生效,最终导致了机器的 load 飚高,处理能力降低,不足以支撑报价抓取回数时的计算能力。原有抓取回数的 qps 峰值约 8k,当新的抓取调度切量到 5k 时,整个实体机的集群 FullGC 大大增多,如下图所示。究其根本,就是请求被打散,消息聚合能力下降导致处理能力降低。当然,最简单的提高集群处理能力的手段就是在集群中新增机器来解决,但是初步估算想要支撑新的抓取调度机制完全切换,需要将原有集群扩容到两倍以上,而实体机的成本又较高,同时这部分的问题是由于代码逻辑与业务逻辑不匹配导致的,所以我们决定对 rebuild 系统进行重构用来支撑业务。


总结一下,支撑我们对 rebuild 系统进行重构的原因如下:


1、业务瓶颈


(1)现有 rebuild 系统不足以支撑新的抓取调度机制;

(2)回数的链路较长,虽然上文中的流程 ② 解决了资源消耗的问题但是拉长了回数链路,缓存(用户)无法及时看到最新的报价;

(3)rebuild 在处理回数时存在缓存清理的逻辑,这部分逻辑原本的意图是防止缓存时间过长用户看到的报价不够新鲜,但是在新的报价抓取调度机制下是可以避免这种问题的,而对缓存的清理会加剧不同环节下访问缓存报价的不一致问题发生。


2、系统瓶颈


(1)rebuild 系统处理回数的实体机器群不易扩容,应对突发情况不能在短时间做出响应;

(2)rebuild 系统处理能力差,在估算下该系统使用几台虚机就可以完成业务诉求,并不需要大量的实体机集群支撑;

(3)rebuild 系统职责不单一,多个职能分布在物理环境不同的集群上但是又共用同一套代码,扩展性较差。


3、学习、维护成本高


系统的设计较为复杂,比如上文提到的流程 ② 使用了环状内存缓存队列并且存在多种情况会对队列进行出队操作完成酒店维度报价的聚合,并且系统由于迭代的时间较久,人员更替较多,部分代码成为祖宗代码。


我们的重构就为了解决上述问题而实施方案,其中最主要的的一点就是将原有的酒店维度报价缓存更替为 wrapper 维度报价缓存,如下图。



相对于原有的过滤、包装、定价三个大环节的基础上增加了酒店维度报价的组装。存储 wrapper 维度报价,读取时按酒店维度读取对应 wrapper 报价再组装。这样,存储报价时仅面向 wrapper 维度报价,不再处理酒店维度的业务。原有的酒店维度低价计算(上文提到的 rebuild 系统职能 2)和报价回数存储逻辑进行拆分,简化了回数链路,职责单一,并且便于后续对低价计算的重构和优化。读取时,由于 wrapper 报价维度从酒店维度中拆散,可以并行的从缓存中读取。例如:香港的热门酒店,一个酒店会有几十个代理商提供报价,原有的酒店维度报价的报文大小 MB 级别,读取时网络 IO 的时间也比较久。而拆散后,可以并行的读取报文再拼装,减低了读取数据时整体耗时。并且在重构的过程中,针对已有的业务进行代码的重新编写,避免了祖宗代码的保留,大大提高了代码的可读性,降低了学习成本。


由于变动了缓存的结构,并对核心主流程的代码进行了重构,为了避免线上出现问题,需要进行可靠的验证。我们 diff 了新老结构、流程中酒店维度的报价报文字段,做到 100%的准确无误。关注了缓存从酒店维度拆解成 wrapper 维度的压缩率以及对缓存存储空间的占用大小。并且对整体报价读取的响应时间进行了评估。


正式上线后,基本符合预期:


  1. 报价回数存储基本不存在延迟,平均回数处理时长 4ms;

  2. 新系统集群由 20 台虚拟机构成,可以处理线上 17k 的报价回数消息并且远远没有触达系统瓶颈,而原有集群的 13 台实体机处理 8k 消息已经触达系统瓶颈;

  3. 酒店缓存报价读取 P95 时长从原有的 80ms 降低到 35ms,平均时长从 30ms 降低到 10ms;

  4. 系统代码文件数从 1001 个文件减少到 171 个文件。





在对 rebuild 系统进行重构后,新的抓取调度机制得以顺利上线。

2.3 项目成果


当然,除了 L-D 环节的顺畅度以外,其他同事也在其他环节上做出了努力与贡献。为了解决 D-B、B-O 环节的顺畅度问题,还做了禁售、实时报价库存更新、报价容差等一系列的项目。从结果上来看通过大家的不懈努力,将国际酒店整体顺畅度提升到了 87%,极大改善了 Qunar 用户在国际酒店售前环节的体验。



售前服务的提升告一段落,后续的文章《国际酒店用户服务能力提升(三)》会聊一聊在售后服务的提升过程中我们做了哪些事情以及在技术上的探索和尝试。




头图:Unsplash

作者:张楚宸

原文国际酒店用户服务能力提升(二)

来源:Qunar 技术沙龙 - 微信公众号 [ID:QunarTL]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


2020-12-10 19:301253
用户头像

发布了 91 篇内容, 共 13.8 次阅读, 收获喜欢 156 次。

关注

评论

发布
暂无评论
发现更多内容

探索区块链交易所的开发之路

dappweb

交易所开发 区块链开发

为什么外贸行业选择使用云手机?

Ogcloud

云手机 海外云手机 云手机海外版 国外云手机

ETLCloud中如何使用Kettle组件

RestCloud

kettle ETL 数据集成 ETLCloud

Moonchain 与穿戴设备 Blueberry Ring 整合,基于自身 DePIN 生态为 IoT 领域深度赋能

股市老人

性能突破|海量客户端场景 Quota 和 QoS 的优化之路

焱融科技

低代码开发与前端架构

不在线第一只蜗牛

架构 前端 低代码

Scroll 上的明星项目Pencils Protocol ,缘何被严重低估?

股市老人

一站式链路追踪:阿里云的端到端解决方案

阿里巴巴云原生

阿里云 云原生 可观测

如何使用前端表格控件实现多数据源整合?

快乐非自愿限量之名

前端 表格控件

从人工向智能化转变,企业级指标管理平台建设实战

袋鼠云数栈

指标管理 指标建设 指标设计 指标设计指标体系 指标搭建

发现了一个全新的后台管理框架,前后端都有

大师兄

Vue 开源框架 nest

Maven 中的 classifier 属性用过没?

江南一点雨

Java maven

30天拿下Rust之输入输出

希望睿智

rust语言 输入输出

CCIG 2024:合合信息文档解析技术突破与应用前景

海拥(haiyong.site)

文档识别

低代码:全生命周期管理的技术革新与应用实践

EquatorCoco

低代码 全生命周期

活动回顾 | 「观测云」为何成为中国峰会可观测性领域的唯一代表?

观测云

AWS

Apache IoTDB 分布式架构三部曲(二)分片与负载均衡

Apache IoTDB

什么是数据资产管理?数据资产管理包括了哪些内容?

优秀

数据资产管理

Scroll 生态明星项目Pencils Protocol,发展潜力巨大

大瞿科技

API测试工具领域,Postman的10个最佳替换

幂简集成

Postman API API测试 API测试工具

Django 实现用户需求及反馈系统并支持图片上传

我再BUG界嘎嘎乱杀

Python django 爬虫 后端 开发语言

软件测试学习笔记丨Selenium 配置浏览器启动状态Options

测试人

软件测试

海外云手机运营TikTok:高效、稳定且节省流量

Ogcloud

云手机 海外云手机 tiktok云手机 云手机海外版 电商云手机

打造高效微服务最佳实践

俞凡

架构 微服务

Scroll 生态明星项目Pencils Protocol,发展潜力巨大

加密眼界

30天拿下Rust之命令行参数

希望睿智

命令行 rust语言 命令行参数解析

Scroll 生态明星项目Pencils Protocol,发展潜力巨大

股市老人

今日分享丨按场景定制界面

inBuilder低代码平台

界面 开发分享

低代码与大模型时代:技术的进化与人工智能的普及

快乐非自愿限量之名

人工智能 低代码 大模型

利用依赖结构矩阵管理架构债务

俞凡

架构

国际酒店用户服务能力提升(二)_架构_Qunar技术沙龙_InfoQ精选文章