原文:

点击蓝色“大数据每日哔哔”关注我

加个“星标”,第一时间获取

大数据架构,实战经验

摘要:

由于影院单日售票在 3000W 张,预售将近 1 亿张票,计算量大,写入频次高,从感知影院售票到客户端呈现数据,采用什么样的方案,什么样的技术,能够通过最小的改动让数据最快的呈现出来,成了技术考虑的难点。主要内容包括:

技术挑战

技术策略

落地方法

总结沉淀

专业名词解释

阿里大文娱 | 奋氛

背景

灯塔是阿里大文娱旗下一站式宣发平台,同时也是阿里巴巴为数不多对外提供数据的数据平台。作为数据平台,数据的时效性和准确性一直技术需要突破的重点和难点。

一、技术挑战

灯塔数据系统(前身淘票票专业版)从 2017年开始建设,最开始采用MYSQL作为数据存储,基础数据定时计算写入数据库,经过2年多的建设,产品已经基本成形,但对于数据的实效性有了更高的要求。由于影院单日售票在3000W张,预售将近1亿张票,计算量大,写入频次高,从感知影院售票到客户端呈现数据,采用什么样的方案,什么样的技术,能够通过最小的改动让数据最快的呈现出来,成了技术考虑的难点。

二、技术策略

首先是缩小数据量,找出数据规律,实现数据的实时计算。各维度数据汇总如图所示:

(图片:灯塔专业版数据汇总关系图)

各维度数据在业务应用的场景中,均可以按照时间、地区、业务主键进行检索。根据这个特征,我们生成了天然的 Key组合,时间、地区、业务主键,并排列组合出三种Key:时间_地区_业务主键,时间_业务主键_地区,地区_业务主键_时间。按照以上三种Key组合,在已知任何两个条件的情况下,均能实现对业务数据的检索。此时我们已经锁定了数据的存储平台HBase。剩下的就是如何改造系统实现实时化。

三、落地方法

数据源有了,MYSQL和HBase。HBase是实时数据,MYSQL是离线数据。为了让上层业务无感知,特在底层数据做处理,实现离线数据和实时数据的结合。数据处理流程如图所示:

(图片:灯塔专业版数据处理流程图)

用户在请求票房数据的时候,先根据业务开关决定请求实时数据还是离线数据。离线数据直接请求MYSQL。实时数据优先查询缓存,若缓存存在且不过期,直接返回缓存数据。缓存数据失效的情况下,查询HBase并重新写入缓存。

系统日常具有高达上千的 QPS,为了避免缓存击穿对数据源造成压力,需要对热点数据进行缓存预热。由于数据的特殊性,T 日为最热数据,占总流量的 80%以上,因此,缓存预热成为承受高并发访问的关键措施。定时任务每秒将 T 日数据整体刷入缓存,以防止缓存失效击穿(因为都是 key-value 存储,后续考虑直接将热数据写入缓存,替代预热方案)。实际上,为了防止击穿,这部分数据是 24 小时不过期的,数据的更新依赖于定时任务。一旦数据链路故障、HBase 故障或算法异常,只需停止定时任务,就能暂时止血,为技术留出处理时间以防止故障升级。同时,HBase 采用主备链路,且主备链路的算法略有不同,以确保主备链路不会同时出现问题。这样的架构为应用提供了 4 套不同的数据源保障。自架构上线以来,数据未出现过一次问题。此外,这种方式在无形中解决了高 QPS 的问题,使数据的提供主要依靠 TAIR,而缓存应对 QPS 变得相对简单。

(图片:灯塔专业版数据源关系图)

系统的难点在于实时数据和离线数据的结合。数据结合可分为以下几类:

1. T日查询,非实时即离线,如查询今日大盘票房。系统首先定义了一个方法,根据日期判断数据应该查询实时还是查询离线。由于行业数据按照 6 点到 6 点更新,即 T 日数据,在第二日 6 点后才变为离线数据。此外,由于专资办数据回刷的问题,需要防止数据回跳,会在数据回刷后才切换为离线数据。当查询单日数据时,根据查询日期判定数据源并进行数据转换;

2. 日期范围查询,即实时与离线相结合,如查询影片每日票房情况。当查询日期范围时,由于日期范围是连续的,因此将范围日期拆分为每一天。按照方法 1 中的判定规则,将日期范围拆分为离线日期和实时日期。然后根据日期范围选择最小日期和最大日期进行范围查询。查询完成后,进行数据组合并返回结果;

3. 范围统计,实时与离线相结合,如本周票房。当进行范围统计查询时,首先查询离线数据。然后根据日期判断,如果 T-1 数据尚未回刷,则查询 T-1 和 T 日数据;否则只查询 T 日数据即可。将实时数据和离线数据相加并返回查询结果。

. 榜单查询,离线补实时,如影片榜单。榜单查询由于榜单数据范围不好确定,范围查询有可能查询数据太多,所以在查询排行榜时,先取离线数据 2 倍的数据量,然后根据离线数据返回业务主键,查询当前的实时数据,将实时数据覆盖到离线数据后,进行内存排序和截取,最终返回榜单数据。榜单数据略有不同,比如院线影片,由于全国院线一共 49 家,此时不做离线查询,直接查询所有实时数据进行排序。

针对以上数据整合的各种可能,参照以往出现的各种问题,封装代码如下:

(图片:示例代码 1)

(图片:示例代码 2)

通过以上处理,在上层业务无感知的情况下,下游数据实现了整体实时化的切换。而且通 过 switch 开关控制针对数据源能够实现单业务主备切流,实时离线数据转换,使得数据的稳定性更可靠,为底层数据改造和升级留下了充足的扩展空间。

有了架构还不够,还需要感知能力,业务异常感知还是比较简单的,但是对于灯塔来说, 有数不代表正常,数据到底对不对,这是问题感知的关键,这时候需要一个智能化的监控系统。针对票房数据,在不改造代码的情况下,我们设计了一个切面,引入脚本代码,针对特定数据来源做数据动态处理,将返回数据整合在一起,并提取出来,通过算法识别票房数据行为趋势。

(图片:灯塔专业版票房监测趋势图)

针对数据的趋势做智能化监控,当数据异常变化或者超过业务限定范围时就会通知告警 以此来有效的规避数据异常的情况并能及时感知问题。

四、总结沉淀随着 B 端业务的发展和海量数据存储和更新的需要下关系型数据库已经越来越无力各种类型的数据存储起到了不同的作用多数据源的整合也越来越重要本文介绍了灯塔为了做到实时的数据系统是如何组合 Mysql Hbase Tair 三个数据源来实现高写入高并发高可靠的数据系统希望能给后续更多业务系统提供参考和指导。

专业名词解释:Tair是一个高性能、分布式、可扩展、高可靠的Key-Value nosql结构存储系统专注于高速缓存场景HBase是一个高可靠、高性能面向列可伸缩的分布式数据库是谷歌BigTable的开源实现主要用来存储非结构化和半结构化的松散数据HBase的目标是处理非常庞大的表可以通过水平扩展的方式利用廉价计算机集群处理由超过10亿行数据和数百万列元素组成的数据表。

缓存击穿是指在使用缓存时,通常我们会先检查缓存中是否存在所需数据,如果存在则直接返回缓存内容;如果不存在,则直接查询数据库并将查询结果存入缓存以供后续访问。这种情况下,当某个热点数据的ID在数据库中不存在时,每次访问都会触发数据库查询,可能会给数据库带来过大压力。

为了解决这个问题,我们可以采取以下策略:

1. 当通过某个key去查询数据时,如果对应在数据库中的数据都不存在,我们将此key对应的value设置为一个默认值(如“NULL”),并设置一个缓存的失效时间。这样,在缓存失效之前,所有通过此key的访问都被缓存挡住了。

2. 等到此key对应的数据在DB中存在时,缓存失效之后,通过此key再去访问数据,就能拿到新的value了。

采用这种策略可以有效减轻数据库的压力,避免因为恶意破坏导致的大流量冲击。同时,也提高了系统的可用性和响应速度。