本文首发于 Nebula Graph Community 公众号
对于用户的每一次查问,都能依据其用意做到相应的场景和产品的匹配”,是携程酒店技术团队的指标,但实现这个指标他们遇到了三大问题…本文着重讲述他们是如何构建场景与信息关系,用 Nebula 解决关联关系,从而疾速返回场景化定制举荐信息给酒店用户的实际过程。
背景
用一句话来概述携程愚公我的项目的需要便是“对于用户的每一次查问,都能依据其用意做到相应的场景和产品的匹配”。
目前,在酒店排序方面,携程酒店曾经做到了针对不同的用户群体和应用场景给出定制化服务:在不同的场景下,酒店列表页面会有不同的排序,取得了很高的用户价值晋升。而携程酒店通过在前端展现场景化内容,也升高用户决策的费力度。
如果以后用户场景是滑雪度假,作为服务提供方咱们天然冀望前端的各个展现位都能与滑雪相关联,如上图酒店列表页中酒店的短标签位展现了一个 滑雪套餐
,酒店的榜单位展现的是以后酒店在当地的滑雪榜排名,以及酒店的展现图片为雪景下的酒店。
酒店详情页中,酒店相册所展现内容也是雪景。相册排序第一的分类为【滑雪精选】,而酒店的其余短标签位榜单同列表页的逻辑相似,展现和滑雪相干的内容。在地理信息位则展现与最近的滑雪场的间隔。
下面两张图别离是酒店和房型的详情信息,在酒店设施、房型气氛图内容出现上,也依据滑雪度假场景做出了相应的调整。
以上 4 张图,简略地形容了携程酒店对于前端各个展现位通过与场景相关联所能达到的一个展现的成果。
而要实现上述性能,首先要把各种场景与内容信息之间建设关联,输出场景的时候就能间接疾速地检索到相干信息进行展现。为此须要解决以下问题:
- 不足场景和信息的 mapping 关系
- 信息的丰富性不够,无奈撑持场景化
- 经营和零碎不够高效
具体来说,场景与信息关联关系缺失的起因是,在愚公我的项目之前,携程酒店前端展现内容互相独立,没有对立的整合体系。像下面提到的特色标签 带娃
、 爱住
标签,设施标签中亲子乐园标签,只管从语义上能很间接地将它们同亲子场景关联,但它们一个是特色,一个是设施,除了应用同一个的展现位之外,标签间并没有其余的共同点。
另一个比拟典型的例子就是点评,上图右侧 App 截图是武汉东湖宾馆的三条点评,第一条讲到亲子出行,第二条讲到赏樱内容,第三条讲到游览倡议,而这三类内容目前仅作为一个酒店点评展现并没有其余更多的作用。而在愚公我的项目中,如果咱们定义了三个场景,一个叫亲子,一个叫赏樱,一个叫游览,关联点评与场景标签,那么咱们能够做的事件就更多了。比方一家酒店,其中有 30% 点评提到了亲子,可能就能够判断酒店有亲子特色。再比方,提到樱花的点评中,抽取出简短、柔美的语句同赏樱场景关联,以后端传过来樱花场景时,这个短句子作为展现补充就能够展现在前端地位…诸如相似用处,咱们能够天马行空、不停的设想,但实现的关键点是建设场景与信息之间的关联。
第二个问题是信息丰盛度不够,无奈撑持场景化需要。举个简略例子,在列表页筛选了滑雪后,没有滑雪相干的图片,也没有相干标签天文的地位信息;在详情页没有滑雪相干的相册信息,也没有滑雪的气氛图,尽管酒店的设施有滑雪设施,但它没有依据滑雪这一场景做出更高优先级的展现,第二设施滑雪设施也没有相干的图片展现,这样就导致酒店举荐生动性有余。
第三个问题是零碎和经营不够高效。具体来说:
-
新场景 & 新数据开发成本很大。每个场景上线,须要依据联动地位一一开发
- 每个地位接入新信息,须要跟版本公布
-
数据时效性:无统一标准,时效性有余
- 例如特色标签,多个 job 串行:T+x 失效
-
数据排序:无对立收口方
- 列表页短标签:动态信息、前端均有逻辑 + 经营后盾
- 排查链路长,日常保护效率低
-
数据规范:有多套规范存在
- 哪些是亲子酒店?
- …
开展来说,携程酒店前端展现位来源于多个服务,比方图中标出的这 十多个展现位,其中就蕴含点评、榜单、标签等一系列服务。如果这些服务的联动逻辑,没有对立收口方,那么每新增一个场景,相应的展现位都须要进行相应的开发,这样开发成本就会比拟大。第二点的数据实时性,目前更新 job 存在局部串行,局部数据经营批改之后可能在 t+x 之后能力失效,实时性不高。第三点是数据排序展现逻辑没有对立的收口方,前后端都有保护相应逻辑的中央,造成冗余信息数据、排查链路变长、保护效率低。最初一点是短少对立数据规范。要判断酒店是否合乎亲子特色,怎么做?如果一个酒店有三个特色标签提到亲子,那么它是否是一家亲子酒店呢?又或者酒店点评中有 20% 内容提到了亲子,那么它是否是一家亲子酒店呢?诸如此类的规范,咱们须要个精确的定义,场景化的规定能力得以施行。
总结来说,要达到前端各个展现位内容的场景化,须要解决三个问题,一个是场景与信息之间短少关联;二是目前的信息丰盛度没有方法撑持场景化;三是零碎的经营效率在原有的架构下不够高效。为了解决以上的问题,愚公我的项目就应运而生了。
愚公我的项目:用户预订全流程信息场景化
下图为愚公我的项目的总体框架。
我的项目框架
我的项目波及到多个零碎的晋升:
- 对立的用意辨认
- 展现地位逻辑下沉
- 关系匹配
- 信息开掘
- 数据源丰盛
愚公我的项目次要分为上图 5 局部内容,从上往下第一局部是用意辨认,次要通过用户的历史偏好和实时数据来辨认用户的具体用意,比方用户他历史点评中屡次呈现了“带娃”、实时的入住筛选项人数中也有小孩筛选项,那么咱们判断他以后用意有很大概率是亲子游览。
第二局部是信息展现逻辑下沉,之前提到前端有十多个展现位,当中的展现逻辑别离有不同的信息服务保护,在这个模块咱们将这些展现位的逻辑对立收口,信息之间便能做到联动。此外,还能达到去重、去抵触等作用,还能够整体地对排序召回等逻辑进行布局。
第三局部是关系匹配,建设场景与数据之间的匹配关系,这里的数据波及存量的根底信息数据,通过开掘失去的增量数据。后期,次要通过人工运维的形式将它们与场景建设一个关联,后续则会应用 NLP 伎俩来主动建立联系。而数据与数据之间、数据与场景之间的这些关系,则会应用 Nebula Graph 作为存储和检索的媒介。
第四局部是信息开掘,即从各类的数据源中抽取出与场景相关联的信息,又或者是酒店的亮点信息。之前提过的点评例子,在点评中找到与场景相关联的句子,从中抽取出通顺、柔美的短句,把它们作为场景化关联的数据源,在前端进行展现,从而丰盛数据源。在信息开掘模块,总体的流程会波及 NLP 相干的数据标注、模型训练、badcase 反馈、标注再训练。
最初是数据源,首先要从尽可能多的数据起源中获取信息,退出图谱中。当然要尽可能保证数据的准确性,间接从源头而非第三方来获取数据。为了保障准确性,后续开发中可能会退出反查机制,比如说某个酒店有游泳池的设施展现信息,通过开掘数据发现这个酒店以后的游泳池设施早已敞开,那么咱们就能够将数据同步给经营人员使得数据更加的精确。
下面 5 个局部,如果将展现地位逻辑的下沉和关系匹配的建设比作一个我的项目的地基,那么其余的模块则是在我的项目上建起的高楼,没有地基哪来的高楼呢?
上面,解说展现地位逻辑的下沉和关系匹配是如何搭建。
前端信息展现逻辑下沉 & 关系匹配
模块的重点是收口前端多个展现位逻辑的数据召回逻辑,建设展现位与场景之间的关联关系。
具体来说,当一个场景进来,零碎须要晓得哪些展现位要与它联动,相应的展现位的数据召回逻辑也会随之变动。举个例子,亲子场景,亲子游、亲子乐园这样的短标签就能够很好地表白亲子的含意,这时短标签位就适宜间接与亲子场景建设关联。而美食场景,某个酒店在美食榜中名落孙山的话,绝对应美食特色标签会更有说服力,美食场景就更适宜同美食榜单进行关联。建设关联关系后,每个展现位是否须要依据场景变动,就有了对立的规范,进而数据召回逻辑也就失去了对立。
上表和图标注了 10+ 个前端展现位和它们的一个联动的等级,联动等级越高,则代表它展示会更须要贴合场景化,也更能找到更多的与场景相关联的信息。
下面是场景与展现位之间如何建设关系,接下来讲讲场景与数据之间又如何建设关系。上图比拟直观,首先要开掘场景,找到凸显酒店特色或吸引用户的点,接着以场景为根底,找到与场景相联动的一个展现位,就像之前提到的不同的展现位能够突出不同的特点,场景与适合的展现位关联能够达到更好的展现成果。最初,通过展现位拓展到相应的数据,而对应的数据可能是已存在或者是为特定场景新增的数据。
举例说明下关系的配置过程,先看一下这张表,当初要定一个新的滑雪场景,首先得判断前端哪些展现位能够与这个场景建设关联,找到了酒店的列表页中快筛短标签、酒店详情页中酒店的头图点评等这些展现位,都能够与这个场景建设联动。而后,只须要通过这些展现位找到相应的数据源和数据类型,配置关系即可。
以短标签为例,短标签蕴含主题标签、设施标签等,这些数据源中可能曾经存在与滑雪相干的内容,咱们能够间接在配置后盾关联场景关系。如果不存在相干内容,也能够由经营人员进行增加,又或者通过数据挖掘产生新的数据源,再进行关联。整个关联在后盾非常直观地进行展现,配置实现后,数据会实时地写入到 Nebula Graph 中,前端就能够间接通过滑雪场景筛选到相干的展现。
撑持信息场景化的技术架构
先从 Nebula 的架构和集群部署讲起,
这张图大家肯定不生疏,Nebula 服务蕴含 graph 服务、meta 服务和 storage 这三个服务。其中,graph 服务用于解决客户端的申请,meta 服务用于存储分片、schema、用户账号等等元数据,storage 则用于存储图中的点边、索引数据。
在 Nebula 集群中数据一致性是依赖于 raft 协定,其中 meta 服务和 storage 服务都是基于 raft 协定的集群。而 storage 服务相较于 meta 服务构造更为简单。具体来说,storage 服务中每一个分片的所有正本独特形成了一个 raft 集群,也就是说 storage 并不是一个 raft 集群,而是有多少个分片,它就有多少个 raft 集群。在 raft 集群中由集群中的 leader 来解决申请,而 follower 用来投票选举、同步数据、同步日志,并为 leader 提供一个候补。leader 会定时发送心跳,如果有一段时间 follower 没有接到 leader 发来的心跳,那么他们就会主动开始选举并产生新 leader,来自 graph 的申请无论是读还是写,基本上由 leader 来响应。
因为 raft 协定特点,leader 的投票须要超过半数以上 follower 投票能力选出,个别集群的部署策略是 2n+1 台机器,这样能够容忍 n 台机器产生的问题。
机器部署
携程酒店的部署形式是三机房扩散比例部署,5n 台 Storage Service,将它们扩散为 1n:2n:2n,这样任意一个机房出问题,另外两个机房都能够持续应用。但这样部署也存在肯定的问题,即使是三个机房但总体而言其实只是一个集群,读取时必然存在跨机房拜访读取带来的时延问题。此外,这种单机房部署的模式无奈反对相似于蓝绿之类的公布形式,也无奈基于就近拜访来调配流量。
这块,将来携程酒店的冀望是每个机房都能部署独立集群,做到按集群进行流量管制和反对就近拜访。当一边集群故障可间接通过域名流量切换到另一边的单边集群,不须要消耗太多的切换老本,而写数据的时候也能够反对蓝绿模式的写入部署。这个模式也让服务出海变得更为切实可行,比方在海内间接部署一个独立集群,可大大减少国内海内读取的时延问题。
这也引出另一个问题,数据同步方面携程酒店是从国内写海内,在这种状况下,同步的实时性和稳定性都不能失去很好的保障。携程酒店也在与携程零碎研发部团队探讨服务端之间间接数据同步的解决方案,如果能实现的话,能够更好地加重数据同步产生的时延影响。
总之,raft 让 Nebula 不便地应答由机器自身不可用产生的问题,下面说的新的集群的部署形式,则是在 raft 根底上让整个集群可用性更高,对于一个携程酒店这样的线上利用容错也更加符合实际的需要。
讲完集群的部署问题,接下来讲讲我的项目的架构。
技术架构
先比拟下我的项目架构的前后变动,上图能够看到原来的架构中,客户端申请的每一种数据起源都有其独立的场景化配置,局部数据源因为没有明确的语义齐全没有方法反对场景化的配置,这就会导致三个次要的问题:
- 开发繁琐
- 实现难度高
- 信息孤岛
第一点,因为信息展现的逻辑离散、存在多个独立服务,无奈造成对立的场景化规范和数据召回逻辑,每个场景化模块须要独自的配置文件和实现逻辑。第二点,像相似酒店图片、酒店问答等类型内容,无奈与场景间接建设关联,只能单纯通过人工经营的形式建设关联,须要消耗很大的老本。第三点,各个信息源的保护没有对立的规范,信息之间互相独立,容易造成不同信息源之间可能有信息反复或抵触的状况,比如说酒店主题和酒店设施中蕴含语义十分相似的标签,如果这两个标签同时展现在前端的话,就会造成信息冗余的问题。
那么如何解决这些问题呢?要搭建一套能够存储各类信息与信息之间的关系,信息与场景之间的关系,以及将信息召回的逻辑进行对立收口的零碎,咱们称之为信息中台零碎。
上图与之前架构的区别,在于把每种数据独立的场景化配置替换成常识图谱模块跟语义标注模块:常识图谱模块用于存储信息与信息之间、信息场景之间的关系,这里咱们会用到 Nebula。通过 Nebula 建设适合 schema 跟映射关系,大部分数据能在两度以内实现查找。语义标注模块则对语义不明确的信息进行开掘、标注,再与场景建立联系。像酒店形容信息、酒店问答信息都可从中开掘有用的数据,补充进常识图谱。
上图略形象,接下来具体地讲讲中台零碎中每一个模块的形成和性能。
信息中台的整体架构从右往左能够分成 4 个模块,别离是信息中台 API 模块、信息图谱模块、常识标注模块和数据模块。
其中,信息中台 API 模块是信息中台对客户端的服务,这个模块起到的作用蕴含场景获取、数据查问、数据包装,整合数据展现逻辑等等。信息中台 API 让相册、标签、设施这些服务由之前的各自蕴含独立的展现逻辑转化为从对立的起源获取展现逻辑。
常识图谱模块次要整合了数据的召回逻辑,应用 Nebula 作为信息之间的一个存储引擎,对于根底数据,比方设施标签数据,将它们与酒店场景形象成点,将它们之间的关系形象成边。而标注产生的数据则会形象成点,与它们与酒店场景之间的关联关系形象成边。当输出场景和酒店 ID 时,通过 Nebula 查问语句疾速地检索到该酒店下合乎场景的所有测试点的索引信息。另外,通过读取实时音讯更新 Nebula 数据,实现实时更新,而不是 t+x 失效,实时性也失去了很大的加强。
信息标注模块大幅度地减少数据丰盛度 ,对大量 UGC、酒店形容内容,在其中找到与场景相关联的信息是比拟消耗资源的工作。这个时候,应用 NLP 相干技术便能提高效率。上图两头局部次要画出了数据在整个信息标注模块中的流转过程。首先预处理点评、图文秀此类信息,失去子句、短句放入标注模块进行标注。标注的时候,会应用语义标签,这些语义标签来源于热搜词或者人工定义等等渠道。在应用语义标签的时候,标签会间接与场景建设关系,个别状况下这种关系是一对一的,但也会存在一对多的状况。标注好的数据会进行模型训练,同动态规定一起进入任务调度模块对数据批量地打标,最初产生的局部数据进行抽样人工 check 之后就能够应用。 这个信息标注模块整合了数据产生的流程,大幅度晋升了数据产生的效率。
最初,数据模块负责的是数据整合和传导,模块数据起源蕴含有信息标注模块产生的各类信息,也蕴含其余从内部同步来的数据。这些数据最终通过数据同步框架写入 Nebula Graph 数据库中。
再来解说数据在数据库模块中的流转过程。特色数据、设施数据、酒店数据等等类型分为全量和增量数据,全量数据蕴含 DB、音讯队列、音讯接口、Hive 表等等,其中 Hive 表间接通过 Hive job 间接同步 Nebula,而 DB、音讯队列、音讯接口则通过 nebula-java 客户端同步。携程酒店联合 Nebula Java 客户端实现了一套可配置化的同步框架,并搭建了信息同步的服务。当数据起源是接口、音讯队列时,通过实现相应的接口组装数据,并配置音讯字段与 Nebula 字段的映射关系实现数据同步。当数据起源是 DB 时,间接用从 DB 中取数 SQL 语句,并配置 DB 字段与 Nebula 字段的映射关系实现数据同步。增量数据次要来源于音讯队列,增量 job 与全量 job 应用雷同映射关系,对于增量音讯而言只需实现组装数据的接口即可实现同步。
除了数据同步之外,携程酒店还有数据经营的平台,蕴含上面 4 个性能:
- schema:收口 Nebula schema 操作,Nebula 自身有图形化界面,携程酒店将 schema 操作收口到后盾,可便于配置权限、记录操作日志。
- 监控:在数据导入过程中,携程酒店在 ClickHouse 看板中记录数据、起源、操作类型、主题信息,便于直观地查看数据统计信息。此外当有谬误产生时,联合报错信息中 Nebula query log 加上 CK(ClickHouse)上的数据,可疾速定位到具体点、边、报错的类型、数据起源、音讯 ID 等等信息。
- 依赖配置:在数据组装时,后面提到有数据源和 Nebula 字段的映射关系配置,每次 job 启动会实时读取映射配置,携程酒店技术团队将配置放到配置后盾,从而实现实时配置实时失效。
- 重试机制:在数据传输谬误产生时,退出重试机制。但音讯队列这类数据自身有重传的机制,只需在数据异样时给出相应标识。而接口、DB 这类数据临时没有重试机制,后续会退出重试机制。
schema 定义和压测
再来讲一下 schema 定义和压测后果。
信息中台图谱数据模型分为 4 个大块,别离是标签信息、根底信息、UGC 信息和 GEO 信息。标签信息中蕴含设施标签、特色标签、长标签、UGC 标签等这些点;根底信息中蕴含了房型信息、设施信息、政策信息等这些点;UGC 信息中蕴含挖掘出的子句点、用户点等信息;GEO 信息蕴含了 POI、省份、城市点等等这些点。酒店作为最核心的点被这 4 块区域所蕴含,同时与下面提到的每个点都有相关联的边。
此外,最上层形象了语义标签点,所有与场景建设关联的点都会有语义标签间接建设相应的边关系。这样,当输出一个酒店 ID、场景 ID,能很快地筛选出当中所有点的信息。这样的 schema 是比拟合乎业务逻辑的,但在理论的上线过程中还是呈现了些问题,其中比拟典型的是热点数据问题。
举个例子来说,A 类型数据量可能是百万级,B 类型数据量是千级,每一个 A 与 B 之间存在关联,那么关联的边量级可能在十万级或者百万级,查问时 B 可能会变成超级节点影响局部性能。
对此,想过几个解决方案。一是减少分片数,用来解决热点数据集中在某一两台机器中的问题,但这样只是扩散热点,并没有彻底地解决热点问题。二是减少逻辑点,将某个热点扩散成多个属性雷同、但 VID 不同的点,这些点同中心点连贯时,通过 Hash 或者其余办法把边打散,但这样不仅减少了数据导入的逻辑复杂度,在某些状况下还会影响数据与数据之间边原本逻辑的准确性。也想过 follower 读这个计划,因为 raft 协定的限度,只有 leader 能解决申请,在一致性要求不高的状况下,是否能够反对 follower 解决读申请,再联合减少分片数,使整个集群中的各个机器的负荷能失去大幅度的平衡——这个问题须要 Nebula 研发团队提供技术支持。
最终,解决热点问题是在携程零碎研发部团队的反对下,通过配置参数解决了个别机器因为热点数据产生的负载过高的问题——计划是别离开启前缀匹配布隆过滤器、加大 blockcache。
上表为上线前做的性能测试图,集群配置是 6 台 graph、5 台 meta、10 台 storage。在 250+ 万点、2 亿多条边的状况下,一度查找在 1 万左右 QPS,在 20 ms 左右;同时写入 10+ 万数据时,在 40 ms 左右;两度查找在 7,000 左右 QPS 时,在 32 ms 左右,同时写入增量数据 10+ 万时,在 50 ms 左右…总体来说,性能上还是比拟合乎业务需要和预期。
此外 Nebula 采纳人造的分布式架构、沉闷的中文社区都是促成携程酒店最终抉择其作为信息图谱搭建平台基础设施的起因之一。
以上为携程酒店信息常识图谱实际分享。
交换图数据库技术?退出 Nebula 交换群请先填写下你的 Nebula 名片,Nebula 小助手会拉你进群~~
Nebula 社区首届征文活动进行中!🔗 奖品丰富,全场景笼罩:撸码机械键盘⌨️、手机无线充🔋、衰弱小助手智能手环⌚️,更有数据库设计、常识图谱实际书籍📚 等你来领,还有 Nebula 粗劣周边送不停~🎁
欢送对 Nebula 有趣味、喜钻研的小伙伴来书写本人和 Nebula 乏味的故事呀~
交换图数据库技术?退出 Nebula 交换群请先填写下你的 Nebula 名片,Nebula 小助手会拉你进群~~
关注公众号