其他分享
首页 > 其他分享> > 【万字详解+PPT下载】腾讯广告实时策略数据框架建设

【万字详解+PPT下载】腾讯广告实时策略数据框架建设

作者:互联网

图片

2021年5月20日-22日,由IT168旗下ITPUB企业社区平台主办的第十三届中国系统架构师大会(SACC2021)在云端进行了网络直播,腾讯广告实时策略数据框架技术负责人林立伟受邀出席,并在大会上就这一议题进行分享

图片

腾讯广告实时策略数据框架,在腾讯广告系统内是负责计算为召回、粗排、精排的整个广告决出过程中的各种影响策略因子,构成整个腾讯广告策略中台的重要组成部分。本文为林立伟的直播实录整理,让我们一起了解实时策略数据框架是如何解决易用性、高性能、高可用三个方面的难题吧!

关注“腾讯广告算法大赛”微信公众号,后台回复“SACC2021”,可下载分享PPT。

图片

腾讯广告中的策略框架

图片

图片

先简单介绍一下腾讯广告,从英文Tencent Marketing Solution可以看出,腾讯广告是一个面向企业的商业服务平台,志在帮助企业做好市场营销。具体到广告流量,腾讯广告基于整个腾讯社交网络体系,不仅覆盖了微信生态中庞大的月度活跃用户,QQ广告也能够触达海量的月度活跃用户。不但如此,腾讯的流量还包括了腾讯视频、腾讯新闻、腾讯看点、腾讯音乐,以及腾讯的广告联盟“优量汇”等。

图片

此次要介绍的整个策略框架在腾讯广告系统中的位置,我们从PPT内可以看到,位于上图高亮红框的位置。在上图所描绘的整个广告系统当中,右上角是广告投放部分,左上角为广告播放部分,而左下角则是整个后台计算部分,其中包括回流日志。在日志回来后,我们会进行策略计算,包括模型训练、报表等。策略就是基于回流日志,进行一些策略的结算,再得到对线上产生的一些实时影响,根据这个策略结果再通过数据通道送回到线上去,进而影响广告的播放

图片

对腾讯广告系统图再拆细了看,我们可以知道,需要面对的日志数量相当庞大,包括请求、排序、曝光、CPM、点击、效果、日志等,有着百T规模的数据量,具体到数据条数,也是千亿级、百亿级的数量。我们所面临的广告的量级、广告主的量级、商品的量级,都是非常庞大的。腾讯广告支撑的许多广告策略,最后都将会将会反馈到线上。

图片

广告系统是按照ecpm进行广告排序,在最后胜出的因素里,除了模型因子的影响外,还有很多策略因子作用在ecpm上。以调价因子为例,调价因子作为帮广告主成本达成的一个因子,具体到达成具备什么样的含义?举例来说:广告主出价500块买一个付费,当他付了三个付费的钱,也就是1500块时,他得到的转化应该是三个,如果转化的数字达不到三个,我们就应该为他进行调节,使得他能够拿到三个转化,调价因子、策略因子便是服务于广告达成这样的目标

图片

策略框架是服务于调价因子的策略部分,对于框架而言,输入就是曝光、点击、效果,这当中会夹杂很多回流预估的数据,包括广告预估、商品预估,及广告主预估的数据等。

此处简单说明一下,回流预估是因为广告从播放到真正产生用户的转化,例如付费或激活等,中间有一段回流的时间,这段时间内我们需要对转化是否能够回来去做相应的预估,这就是回流预估。

基于前面所看到的输入数据,为了产生策略因子,还需要跑很多不同的策略,以适用于不同的场景,对此我们会有多个版本的策略和实验,最后再把策略跑出来的相关结果因子,重新推送到线上产生作用。在整个过程当中,提出整体计算实时性的需求。

图片

调价因子其实只是一类具体的策略,线上不同类的策略有很多,都是来自于各个团队所贡献的策略。而如果每个团队都从头到尾做一遍,包括数据的输入、字段的聚合、参数读取、策略计算,再到结果输出等,整体流程及开发效率,包括系统的运行效率,系统的稳定性等都不能够有保障。具体而言,整体开发效率不高的原因在于大家做了很多重复性的开发工作,发布周期会因此拉长,可能需要几天才能发布一个版本,并且相互之间的效果还可能存在冲突。

其次,在各自开发的时候,策略团队中并非每一个团队都具有非常好的系统优化经验。另一方面,业务上线还有时间约束,时间限制下可能无法做到精细的系统优化,从而导致整个策略的计算耗费更多计算资源,实时的反馈也因此无法达成。当你得到的计算结果,需要经过十分钟、二十分钟才能反馈到线上,属于比较延迟的状态。

最后一点,各自完成策略工作难以保障整个业务的稳定性,因为团队不太会有整体系统化的可用性建设。

图片

因此建设一个统一的整体策略计算框架是非常有必要的

腾讯广告从几年前开始做的就是树立统一的策略计算框架,便于将策略开发和计算归拢起来这可以很好的解决刚才提及的问题,包括易用性的解决问题,使得大家对策略开发和迭代都会有非常高的效率。我们现在基本上做到了每天进行一个策略计算的迭代改动和上线,并且每天都会发布。此处简单解释一下,这跟模型侧的例行训练不是一个含义,我们的迭代和更新是指策略的计算逻辑每天都会做代码的变更,进而每天发布上线,使得线上的策略逻辑计算做相应的改变,属于天级别迭代的情况。

第二点,整体系统的最终性能非常快,运行时处于分钟级和秒级延迟的水平。

第三点,我们做的系统更加稳定、可靠,故障的恢复也会更快

上图右侧是腾讯广告计算策略框架的简化版总览图,首先策略框架是分布式的、最底层部分还是基于腾讯内部 TEG 基础平台的工程师提供的大数据组件,包括上面提到的分钟级和秒级的运行速度,都是是基于Spark Streaming和Flink作为底层的计算引擎,以TubeMQ作为我们消息的中间件,以HBase和HDFS作为我们的可靠存储。

继续看上图右半部分,往上为腾讯广告提供的统一实验配置,包括字段聚合和数据统一读取,再往上会提供给策略一个统一的接口,再往上便是各类策略不同的具体实现,最终我们会把策略的计算结果进行一个统一输出,并反馈到线上。

图片

所以,关于如何解决上文提及的三大类问题,我们将分成三部分来谈。首先分析易用性部分,腾讯广告是如何解决的。

图片

易用性

图片

1.1

抽象日志聚合逻辑&抽象广告数据流

图片

策略数据的聚合部分所面对的需求场景是比较复杂的,举例而言,一个广告到底有多少个转化数?这类的指标其实需要有一分钟、十分钟、天级别以及到现在为止的完整时间轴等多个时间维度来评估这个广告的转化是多少,另外还要区分所谓的播放口径和效果口径。这两个口径的区别在于,当一位用户在今天看到广告并点击后,可能在第二天才发生付费或者激活的转化,那么这个转化算在哪一天?第一天还是第二天?这在口径统计上有所区别。所以,哪怕是广告转化量这一单一指标,其需求仍然是非常不同且复杂的

图片

为满足这样的需求,腾讯广告会设计一个聚合key,也就是在广告中囊括流量及广告位,同时与时间周期和口径等统计维度进行交叉,最终提供一个多维度交叉出的指标和数据。

图片

不同数据维度代表的策略业务语义也不一样,使用的方式和数据特点也不同。例如,有的业务侧重于实时性的需求,有的则侧重于非实时性的数据来判断历史状态,也有业务需求用不同的消耗曲线等等。对应的,引入这些不同维度的数据,其技术实现方案也就不完全一样——需要实时数据,就运用实时的聚合,其他情况下,采用预先聚合,或者通过词表的方式来引入,这样就形成完整的数据模型,我们便能看到不同维度交叉出来的结果和数据模型。

图片

上图表达的依然是数据输入和依赖的问题,在输入的数据流非常多的情况下,策略同学要怎么方便的使用?我们仍以回流词表来做举例,回流词表本身是有多维度和多版本的,如果在最终的框架里把多维度和多版本的词表分别进行加载,依赖的路径会比较多,稳定性往往也会比较差。每个词表需要各自做独立的解析和加载,在开发和使用的过程中都会造成不方便。针对这个问题,最终的方案是对策略业务的逻辑进行抽象,最终呈现出来的就是上图右上侧表格所体现的数据模型。它的key中包括了广告、广告主、广告商品等,而不同列实际就是不同的语义,包括回流率、在线广告的参数、冷启动的参数等。

下一步是用HBase来进行KV表,也就是把不同团队生产的不同数据经过HBase收口,汇总到一个KV的结构里,再把它透传给后面的策略框架,这样就会拥有更好的易用性支持

1.2

灵活的策略接口

图片

易用性的第二个方面在于策略接口。经过不同实现的调研,最终选择的是在框架里直接调用策略代码,也就是说把整个策略代码的实现内嵌在框架当中去运行,以这样的方式实现易用性。

图片

所以每增加一个新的策略,其实相当于增加一个新的接口调用,而所有的接口调用,包括策略实现等,事实上都是无状态的。在给定了特定的输入后,其最终产出就是确定的。如此我们就可以在离线状态下进行复现,也可称之为单机的调试开发或者debug。对于策略同学而言,当整体输入由离线转储到本地的时候,便可在本机离线状态下复现策略的计算情况,其原因便是整个策略计算是处于无状态的。

另外,在整体实验中,包括框架侧连通整个实验系统等,相关的线上参数,例如本次实验是否命中,以及命中之后各个具体的参数的值,都是策略可见的,这样做实验就会非常方便,并且整体实验的参数结果能够持久化的保存下来,可以便捷地在事后复现当时的实验情况。如此下来,实验的整体效率能有大幅度的提升

1.3

多格式、多用途输出

图片

易用性的第三个方面,在于跑完整体策略计算之后的输出,仍会是多格式和多用途的,能够服务于整个框架中各类应用的同学,包括开发、测试、运维、产品、行业服务等,都能够非常方便地获取到框架的输出结果。对于开发和测试的同学而言,每一次在线策略计算的迭代运行输入数据、实验参数,都可以离线转储到本地,方便在本地进行调试和复现结果,而测试的同学也可以进行回归测试。对于运维的同学,腾讯广告提供了两个详细的线上发布的整体版本,即当前正在运行的版本和将要发布的新版本之间数据的diff整理而成的输出报告。同时腾讯广告也提供了诸如Web界面以及Kibana等可查询和交互的图形化方式给到包括产品、运营、支持和行业服务等非研发类的同学也可以借此进行策略、效果和相关问题的排查

所以,这些输出方式实际上都是相互配合的。为了满足各方同学的需求,我们透过抽象等方法实现多种输出方式,包括通过消息队列送到线上进行秒级的生效输出到分布式的关系型数据库输出到HDFS以及输出到TubeMQ来对接Kibana这样的图形化查询方式

图片

经过上述策略输出方面的优化,开发测试效率都会大幅度提升。优化后,策略开发或者新的迭代,从开发周期而言,将从周级别降到天级别,即一天内就可以完成整个开发和测试。对于发布上线而言,几年前只能一周发一版,在经历过去两三年的迭代后,如今每周能够发五版,日均能够发一版,效率得到极大的提升。最后,解耦各个团队之间的工作,整体的排查速度也会提升很多。

图片

上文所讲的第一部分涵盖了运用易用性来解决业务开发效率的问题,在第二个部分,将谈论如何高性能地保障整个系统的运行速度

图片

高性能

图片

2.1

数据处理优化

图片

首先回顾一下,在整体输入数据量非常庞大的状况下,每天千亿级别、百亿级别的数据条数,百T级别的数据量,带来的问题是将对CPU带来在数据读取和解析上的大量消耗。仔细分析策略的业务特点,实际上有的字段并不需要去解析,因此在原始输入的上千个字段当中,只需要解析实际需求的百个字段即可。所以,这当中就会有产生我们称为部分解析的实现需求。

另一方面,对输入层而言,策略用不到的数据实际上可以尽早地进行滤掉,如此能够极大地减少后续处理流程的时间和机器消耗。

图片

此外,还有部分数据不需要全量的数据就能够做相关的计算,例如,分位点这样的一些数据其实可以作为采样,在牺牲一小点准确度的前提下,节省大量的机器资源消耗。

还有一些数据触点上的优化,可以先进行一些集中的数据预处理,后面在多次使用的时候,引入分布式内存的缓存,通过计算框架里边分布式数据集缓存的方式,后面在多个策略进行处理的时候,即可直接访问同一份缓存数据,就不需要再往上倒推到前面进行一个多次的数据预处理。通过这种方式,能够减少很多数据处理上的消耗。另外,更激进的推测执行的策略,也能够减少抖动和降低时延

2.2

外部系统交互优化

图片

前面讲的是高性能的第一部分,主要介绍的是输入数据处理上的优化。第二个部分则是与外部系统交互的优化。在整个策略计算框架与外部系统交互的过程中,进行完分布式计算后,会去连接分布式的数据库,这里的耗时跟广告数量是成正比的。此外,也有一些优化思路可以减少广告数,包括增加并行度、单独的部署集群等,即再部署一个数据库的存储集群,将它和计算集群放置到同一个IDC中,如此将节省一些网络传输带宽和耗时。但这样操作的成本较高,并且对于物理结构的部署会有一定要求。

腾讯广告最终采用比较明显的优化方案,是把整个策略的输出本身去做一个diff,这里的diff是策略同学无需负责的,从策略框架的底层去帮助策略侧完成输出diff的相关事项。

策略输出结果diff的比对,如果这一次跟与上次结果不符,那我就再去从框架侧将结果写出。能够如此操作,其实是因为有的时候策略计算本身虽然看到了一个新的数据输入,但是策略计算的结果并不一定会改变,也就不需要把最新的结果再输出出去。所以,当我们完成这一版优化,整体的改善效果明显,写出量降低非常多

图片

随着策略的增加,整体输出耗时也在增加,跟策略数量成正比,策略越多,耗时越大。分析整体策略业务的特点,我们会将比如相同的存储、相同行不同的策略等,这些写到地方的结果进行汇总或者聚合,如此便能减少对同一行的多次更新。其他的优化,例如在查询HBase的时候尽量缩减查询次数,只在命中了实验的广告时才去查询对应的数据,以及一些共享连接池等的优化,我们也都是做进整体策略的计算框架当中,作为一个底层的优化,直接对上层策略进行一个透明。

所以,总结起来一个比较重要的思路或者做法是一方面分析我们广告数据业务的特点,并且根据策略的业务特点实现特定的优化。另一方面,这些优化本身,对策略同学是不可见的,他无法得知优化的具体细节,但是在使用的感官上,整体框架会跑得非常顺畅,时间大幅缩短。对于框架侧的工程师而言,做这些优化还是非常必要的,多花一些时间进行分析和调优,对应做出工程上的优化。对于研究员序列的同学,可能不太会耗费时间和心思在这种工程类的优化问题上,而是更加关注整体策略计算部分的更新和逻辑上的迭代

2.3

计算调度模式优化

图片

第三个优化,则是在计算调度模式方面的优化。我们将它总结为自调节实时负载均衡,也就是分布式环境下的负载均衡。具体的现象我们可以观察到,不同的并行度在跑策略计算任务的时候,处理不同的数据,它的耗时情况是不同的。

上图右侧可以看到,上方这组以三个并行度分别处理三个广告来进行一个举例,可以观察到并行度虽然处理的广告数均为三个,但是实际上每个并行度的计算耗时存在较明显的长尾效应。也就是说,虽然并行度上的数据条数是分布均匀的,但是并不代表最终计算下来的耗时是均匀的

如何对此进行升级和优化呢?上图右侧下方的部分,我们会实现这样一个调度模式,就是我们将原来三个耗时比较长的广告,分配到不同的并行图上去做,每个并行度里边都会有耗时长和耗时短的,整体下来耗时并非一个绝对的均匀,但是相对于原先的情况而言,整体阶梯的方差会小很多。

如何实现这样的一种模式?原理其实是策略数据的计算,是一个多次循环也可称为多次迭代,整体过程就是下一次迭代的计算跟上一次迭代计算的耗时相对而言变化不大,尽管就全天而言,高峰时段和低峰时段的耗时可能仍旧不同,但是它其实还是一个相对缓慢的变化过程。也就是说,每一次的计算跟上一次计算之间的耗时差别其实并不是很大。

所以,根据前几次的反馈拿到的耗时信息,是能够大概计算和知道本次计算的耗时。因此,我们刚才讲的前提是基本成立的,当然它并非每次都成立,但就统计而言,若是大多数情况下是成立的,整体模式优化就会非常有效。

当然,在应对突发情况或者特殊情况的时候,还会有一个对应的回退的策略,例如,在刚启动没有耗时信息历史的时候,或者是运行环境变化较大的时候,都会回退到默认的策略,重新进行计算数据耗时情况的收集。

图片

上图是对先前所讨论的运行过程再进行稍微详细一些的展开,这是由于我们是一个分布式的运行,因此会有一个主控节点。主控节点首先会在不同的并行度上记录和累加数据运行的耗时,当耗时信息返回到主控节点的时候,它就会以此去做一轮任务的重新分发和调度

具体的计算和调度方法,可以看上图左边部分的图示。以四个广告为例,广告1、2、3、4,被划分为了两组,广告1、2在一组,广告3、4在另一组,先运行一轮之后,收集到的耗时信息分别是5秒、6秒和1秒、2秒。这个时候就可以再进行一个重新的分组,把广告1跟4搭配在一组,广告2跟3搭配在一组。

这里“一组一组”的概念就是指搭配到不同的并行度,分配到两个并行度上去,使得广告1跟4在第一个并行度,广告2跟3是在第二个并行度,这样使得他下一次策略计算的耗时能够相对均匀。所以,每一轮的迭代和计算都需要把他的分组信息重新进行下发,因为每一轮都跟可能与上一轮的分配信息不太一样

图片

上图是更详细的整体计算过程,左边仍为输入,这里重新列举6个广告的案例,上面是输入,下面是如何产生两个并行度的分组输出。具体的执行过程是,我们会把输入的6个广告先进行倒序排列,目标是要把它分配到两组,也就是两个并行度当中,因此先把两个耗时较大的广告分配进去,接着继续往下分配下一个广告,一直往下分配,在一定的条件下还需要进行分组的交换。交换完分组后继续往里分配,在遇到一定的终结条件后需要对分组或者并行度进行归档。这样整体计算过程都跑完,就会得到上图左边红框内的输出,并行度1里会包含2、5、3,并行度2里会包含1、4、6这样两组的广告,使得耗时情况相对均匀

图片

做完优化之后,可以观察到相对明显的优化,在4000多个并行度的任务上面,原来的长尾在20秒左右,整体的标准差是2.57,在做完相关优化后,整体的标准差能够回到1.36,长尾耗时显著减少

图片

我们所面临的第三个问题,是如何实现高可用以提升整体业务的稳定性,这当中的挑战和业务价值是很大的。

图片

高可用

图片

图片

上图是一个总览,广告系统整体是非常复杂的,回到策略数据的计算,上游输入的部分其实是挺复杂的,其中包括各种不同的日志回来之后,需要经过CGI、日志网关,再经过TubeMQ走日志关联,还需要经过HBase和TubeMQ进行一个转发,到广告主侧还要进行一个回传,到我们这里接着进行一个归因,最后是经过消息队列到我们整个框架里。所以,最终进入我们策略计算框架的上游输入是比较复杂的,或者说回传这里其实具有较大的不确定性,其中有很多的挑战

图片

在公开财报里边,腾讯广告现在的日均收入是将近三个亿,在“6·18”或“双11”等特殊节点会更高,所以为了稳定线上收入,我们会做很多可用性相关的建设工作,总结下来包括一致性的保障、检查点的机制、故障链路的优化等,下文会进行展开详细介绍。

3.1

主备一致性保证

图片

腾讯广告的策略框架部署了多套,每一套都有主备、热备这样的保障。涉及到主备问题,我们就需要去看主备给出的策略结果如何保持一致。

我们这里最终考虑整个易用性和可维护性采用的方案,在不需要秒级延迟,分钟级延迟、或者半分钟的延迟就可以接受的时候,我们这里先把数据从TubeMQ里面先落地到HDFS可靠存储,对于主备两个任务,他看到的是同样HDFS的可靠存储的数据,策略、而在计算本身中间没有随机性的状况下,我们说主备这两套框架跑出来的整体结果就是一致的。包括最终的数据可追溯性方面,我们也是基于HDFS上的目录来组织时间的结构,回溯起来可以到任意区间和任意时间,非常的灵活

图片

另一个相关问题,当主备两套都在跑时,输出到底是要主备两套同时输出,还是做主备切换这样的输出。我们最终给出的是采用主备切换的输出方式,在正常运行的时候,只有Master这一套,也就是主这一套来去写,在发生主备切换的时候,才会有Slave这一套来去写现场结果

这需要考虑几个方面的因素,一个是整体因子的变化,我们希望它是线性的,从另外一个角度来说,当我们采用这样的一个主备模式,我们天然的就会把备环境来当做一个发布灰度的环境,也就是说在进行线上发布的时候,由于我们每天都会发布,就会把需要发布的新版本先在备环境上去跑,跑一段时间后,观察其跟主环境之间策略数据上的diff,如果没有策略数据的diff,或者这个diff在预期的变更范围之内,我们再去把它给更新到主环境上去。

这种方案效果可能需要有一个trade-off,要在任务配置和代码逻辑里边都去做适配,来区分主和备的区别

3.2

检查点

图片

可用性第二个要介绍的部分是关于检查点这部分主要面临的问题在于当我们的整体策略计算框架出现问题进行重启之后,要如何进行状态快速恢复。首先我们面临的难题是输入的数据不可能再进行一次全量的计算,因为数据量太大,所以,需要做的是增量的计算。我们可以把输入数据切分成时间分片,例如按照每分钟或者每半分钟做数据分片,每次都在这基础上做增量计算,基于上一次我们保存的检查点状态,再累加本次时间片看到的数据输入,最终计算出来的就会是一个全量的状态。这当中有一个实现上的细节,就是当我们在做上次Checkpoint跟下次增量输入数据之间的Join时,我们做的实际上是一个本地化的Join,或者也可称为Co-partition的这样一个同分区的Join的实现。

具体检查点的实现是基于自定义的,前文中有说到,虽然我们的底层是基于Spark、Spark Streaming这种的计算引擎,但是我们的Checkpoint是没有直接用Spark也没有用Spark Streaming原生的Checkpoint,这是基于一些诸如存储优化、兼容性等方面的因素考量。除此以外,此处还可以做一些优化,检查点上可以做一些内存里面的缓存,这样整体在恢复速度上、准确性上、整体存储资源的节省上,都会有比较好的产出最终反馈出来的整体Checkpoint做检查点的过程,以及失败重启之后的检查点恢复过程都会非常快,端到端的整个计算时间内就会非常低

3.3

故障处理链路优化

图片

可运性的第三部分在于故障链路的优化,这需要做一个处理问题和缩短恢复时间的自动化机制,上图是我们在某一年的“6·18”大促前后观察到外部数据的一些多多少少的故障,主要的挑战还是来自于广告主本身,大大小小的广告主的技术能力其实还是有差别,就会产生不同广告主回传的效果上报的问题。

图片

在真的发生相关问题的时候,一方面需要去尽早感知问题,包括进入“熔断模式”另一方面要尽早处理相关问题。举例来说,当广告主发生回传数据堆积的问题,经历一段时间的故障后,广告主完成了修复,此时我们会看到的现象是广告主在一段时间内没有数据进来,随后突然回来大批量的数据,此时我们就需要进行一个数据的快速追赶。

打个比方,正常的时候策略计算是一条一条的去处理输入数据进行策略的计算,在这种情况下就需要去一块一块地去处理数据,处理完一块,也就是很多条数据之后,再进行一次其中策略的计算,这样就会节省很多的策略计算时间。在我们演练实测的过程中,延迟一个小时到达所积累的数据,我们可以在两、三分钟内追平。

这当中免不了人工的介入来进行相关的判断和处理,在进行了人工的配置之后,所有配置可以直接在生产环境是热加载和热生效状态下完成,不用先停机再来做相关异常数据的处理,包括黑名单的加载等

图片

总结

图片

图片

最后进行简单的总结和回顾,本文主要介绍的是腾讯广告整体的实时策略计算框架,包括解决易用性、解决系统运行速度、保障可用性快速恢复等,并介绍了具体的设计实现和优化,最终目的是为了达成腾讯广告收入目标,以及帮助广告主的市场营销布局

腾讯广告算法大赛报名火热进行中

图片

实时策略策划框架的内容就分享到这里,最后再分享一个信息,腾讯广告算法大赛正在火热报名中,参赛选手将有机会挑战百万现金奖池和ACM Multimedia顶会加持,本届赛事即将在2021年6月4日截止报名,赶快报名吧!

标签:万字,策略,腾讯,耗时,详解,广告,计算,PPT,数据
来源: https://blog.csdn.net/weixin_45676602/article/details/118358012