首次揭秘!大麦如何应对超大规模高性能选座抢票?
作者| 阿里文娱技术专家恒磊、高级开发工程师新钱
出品 | AI科技大本营(ID:rgznai100)
背景介绍
随着现场娱乐行业的不断发展,各类演出层出不穷,越来越多的演出开启选座购票满足用 户的自主选座需求。大麦的选座不仅面向中小场馆类的剧院演出,还面向大型体育赛事、大型 演唱会等超大型场馆(如鸟巢近 10 万座)。
选座类型抢票的特点是“选”,由于“选”的可视化以 及超大场馆在数据量上对大麦是很大的挑战。本文通过服务端和前端上的一些解决方案来探讨 如何支撑超大规模场馆的高性能选座,通过本文的一些技术方案希望可以对读者在一些高并发 实践中提供帮助。
核心问题
首先看一下普通商品的秒杀,拿某款手机秒杀来说,一般情况下,一场手机只有几个型号, 比如中低档、高性能档、旗舰等,处理好这几个商品的库存即可。对于选座类抢票而言,每一 个场次的所有的每一个座位都可以认为是一个不同的商品,场馆大小不一,大的鸟巢有 10w 座 位。也即是说一个选座类抢票就涉及 10 万级别的商品,如果多个项目同时开抢,整体数量会很 庞大。目前大麦电商侧的商品维度是票档,座位并不是商品粒度,所以无法利用集团的秒杀能 力,选座类抢票涉及电商、选座、票务云产销,是对大麦整体能力的考验。
先来看看整个选座购票的流程:以林俊杰长沙测试项目购票为例。
1、用户打开需要的场次项目详情页
2、点击选座购买,打开选座页面,查看座位图及票档
3、选择一个看台区域,选择喜欢的座位,点击确认选座
4、进入下单页面,填写手机号收货地址,创建订单
5、提交订单完成付款、出票。其中,2、3、4 环节都与选座相关。从流程上看,选座的核心关键技术在于:
座位图的快速加载。快速加载其实就是选座页面的读能力。选座页面需要下载座位底图、 座位基础信息(排号等等)来做渲染,同时需要票档、该场次每个座位的状态,来决定是可售还是锁定还是已经售出。对于大型场馆座位 5 万-10 万,渲染一个选座页面需要的数据量都很大;
高并发。由于热门演出票的稀缺性,同时抢票的人数可能达到几十万。如何支撑如此高 的并发和吞吐是一大考验;
座位状态更新的及时性 当某个座位售出后,需要及时更新座位状态;
抢票体验:抢票时热门的看台某个座位可能几十个人并发去抢,如何尽量提升用户的体 验,尽量让更多用户一次性购买成功,体验更好。
高性能选座实践
针对高性能选座的核心要求,我们从如下几个维度去阐述我们在选座类抢票上的实践。
1. 动静结合
选座的瓶颈数据量“首当其冲”。从逻辑上讲,一个座位完整的展现到用户面前,需要包含 座位的看台、排号、价格、售卖状态等信息,其中 看台、排号等等是不变的,并可提前预知的;售卖状态等时根据项目的进行会动态变化的。所以把选座的数据拆分为动态、静态数据。对于 大型场馆如 10 万场馆,用户打开一个选座页,座位的静态数据(座位 id,票价 id,是否固定套 票,坐标 x,y,和舞台角度,哪个看台,几排几号等等),这些数据大概 15M 左右。再加上动 态数据如票档状态、颜色、看台状态、座位状态,10w 场馆大概 2M 左右。
也就是说,如果不做处理用户仅仅打开选座页就需要 17M 以上的数据量。如果选座数据存储在 oss 上,如果每人下 载 15M,10w 人同时抢票则需要 1500G 带宽,带宽成本很高。为了解决静态文件访问速度问题, 将静态数据从 oss 直接接入到 cdn。同时为了保障数据最新,静态数据采用版本控制。
2. 静态数据的预加载
上面提到带宽峰值很高,为了降低峰值且提升体验,客户端引入了静态数据预加载。静态 信息结合预加载的处理,为处理大数据量的座位信息提供了时间上的余量,用户在打开选座页 时优先显示静态信息,可有效降低用户等待时间,提升用户的体验。
通过大数据分析结合用户的行为习惯,确定预加载的场次类型,提高预加载的命中率。
图 2.1:预加载调整流程
预加载+预解析,完成了绘制基本场馆信息的数据准备,再将数据提前与画座 View 绑定, 预渲染 View 进而达到选座页秒开效果。
3. 座位数据编码
动态、静态数据量大制约了我们实现高吞吐,同时也浪费了服务带宽和用户流量。所以需 要压缩,压缩到一定的可接受的范围。只有数据量足够小,才有办法做到高吞吐。
1)静态数据编码
在处理大数据量的座位(例如十万级)仅有静态数据的预加载往往是不足的,预加载并没有从根本上处理座位数据量大的问题,同时对于类似体育比赛这种多日期多场次的场景,由于预加载的使用存在缓存量的控制,往往影响预加载的命中率。而数据重编码和数据压缩的使用,是从源头解决问题的有效思路。
座位数据的重编,舍弃传统的 xml 和 json 格式,不仅可以有效压缩数据大小,还对数据安 全提供了保障,即使被拿到了接口数据,因为缺乏数据编码的协议,也无法获取有效的原始信息。
2)座位静态数据压缩整体框架
目前大麦针对自己特有的座位数据特点,结合高效二进制编码方案进行座位数据的重新编码,再使用通用的无损压缩进一步缩小数据体积,从而减少了座位数据的网络传输时间,从根本上解决大数据传输导致的时延问题:
图 3.1:静态数据压缩流程
基于二进制的数据编码,既保障了数据安全性,又保证了在数据解析中的高效性,即使数 据压缩的使用也比 json、xml 的解析具有更少的时延。同时兼具工具化的批量生产方式,又进一步解决了数据构建问题。
图 3.2:静态数据压缩工具架构
通过端上和 server 端的握手协商过程,实现了数据编码和通用压缩方式灵活组合,sever 端 可以针对不同的端下发相应的压缩格式文件:
图 3.3:静态数据压缩,握手协商工作流
结合 CRC 的思想,制定了兼容 IOS、Android 和 H5 三端的基于座位属性的纵向 hash 校验。相比 md5 等普通的散列计算方式,在处理 6 万级座位多维度信息时,在端上实现了十几毫秒、 H5 侧 50 毫秒左右的全量数据检测,使得在不占用多长时间的情况,可以验证数万级座位解析 的准确性。经过这编码到检测的完整链路,实现了减少数据的体积的同时,又能达到比传统 xml 和 json数据的高效解析、高安全性。
图 3.3: 压缩数据对比
其中 quantum 是大麦端上自研的基于动态比特和字典的压缩算法,结合大麦特有业务场景, 实现了高压缩比和快速数据解析:
图 3.4: quantum 压缩文件结构
3)座位动态数据的编码处理
a)动态数据的难点
选座动态接口主要涉及票档情况、看台情况、座位状态。数据量最大的是座位状态。以一 个 5 万座位的场馆为例,每个座位都要返回一个状态供前端渲染。采用座位 id 和状态键值对的 方式,由于座位较多使得整个返回结果过大,5 万座位的场馆返回 1M 以上的数据。
如果打开 一个选座页需要吞吐 1M 数据量的化,接口基本不可用了。之前的策略是按照分组策略,5 万 大概会分 10 个组,这样每个请求大概 100k 数据量,这样才能达到接口基本可用,不过端上需 要请求 10 次才能拿到整个场次的状态,可想而知性能会有多大影响。假如 5 万座位的场馆,10 万峰值抢票,那么仅仅这个接口就需要 100 万的 qps,所以肯定会逢抢必挂。
b)方案
目前接口是通过 mtop 协议,我们思考的前提:目前 mtop 不支持 byte[]数组流,只支持 json等格式的字符串结构。如何把返回的数据减小,采用一个尽量简洁的方案,同时调用一次返回 整个场馆座位状态,是我们努力的方向。
数据量大主要是因为有很多冗余的座位 id。有没有办法不依赖这些座位 id?既然我们做的 动静分离,静态数据里已经涵盖了座位 id,我们动态接口里只需要对应的返回状态即可,即按 照静态里面的顺序返回座位状态。同时我们把返回结果进行简单的相邻状态合并将进一步降低 返回结果大小。假设用户选座座位符合正态分布概率,平均长度 5w 座位平均返回不到 20k。
当然如果我们 mtop 协议支持二进制流,那么我们可以用 bit 位进行存储,可以进一步降低 返回结果的大小。
4. 高效缓存
1)缓存
面向这么高的 TPS,tair 是不二首选。采用 tair + 本地缓存,来支撑如此高的数据峰值。提到 tair,提一下我们这边的一些策略。用户进到选座页是一个个的看台,我们设计了一级 stand cache,即看台级别的 cache;用户会进行选座位,我们又加了一级 seat cache,即为座位粒度的 cache。两级 cache 保障用户查看台和用户下单选座都能命中缓存。standcache 是热点 key,从选座的场景是允许数据非准实时 的,所以引入了 tair localcache 和 guava localcache 来增加吞吐,以此降低对 tair 的读压力。
2)保护下游系统
目前采用的策略是 对下游的调用采用加锁,tair 全局锁。拿到锁的才去请求票务云底层数 据。拿到锁的进程去更新 tair 缓存。其实从这里看对 tair 的写还是 qps 比较小的,但是每次争抢 锁对 tair 的读还是不算太小。通过采用本地的锁 + 随机透传来减少 tair 锁耗费的读 qps。为了 对下游依赖做降级,增加了数据快照,每次对下游的调用记录数据快照。当某次调用失败采用 之前的快照进行补偿。
3)保障数据更新及时
由于我们采用了 tair 全局锁,可以按照秒级控制下游调用。调用采用异步触发。最短 1s 内 会触发我们发起对下游的调用。如果我们想最大化利用票务云库存能力,给用户的延迟在 1s 以 内,我们有一些策略。拿到锁的线程 1s 内调用数据更新任务,在数据更新任务里做一些策略, 1s 内是发起 1 次还是多次对票务云的调用,调用越多 tair 更新越及时。由于用户有一定的选座动作,一般情况下 500ms 的延迟用户基本无任何感知的。
4)缓存预热 预热一下缓存,对用户体验和系统性能很有帮助。抢票类项目采用一定的策略做自动化预热。
5. 安全及容灾
1)安全
从上文看大麦座位数据做了编码和加密,同时存储路径做了混淆,保障不到开抢时间座位数据无法被破解,保障了选座数据的安全性。此外选座页布局防控策略,保障是真正需要点击座位才能完成下单,防止机刷、防止绕过选座直接下单。通过类似策略降低了选座的无效流量, 提高了稳定性。
2)容灾
选座主要在以下几个方面做了容灾。静态数据存储在 oss 上,目前采用跨地区存储容灾;tair 缓存采用主备缓存,出故障时可以做切换;服务端在 pc 和无线做了集群隔离。
总结
本文通过在数据处理、选座性能、缓存等等策略上来阐述了大麦高性能选座上的一些实践。通过这些实践目前大麦可以轻松的承载数十万人的顶级流量的抢票项目。
【end】
欢迎所有开发者扫描下方二维码填写《开发者与AI大调研》,只需2分钟,便可收获价值299元的「AI开发者万人大会」在线直播门票!
推荐阅读全球呼吸机告急!医疗科技巨头美敦力“开源”设计图和源代码使用大batch优化深度学习:训练BERT仅需76分钟 | ICLR 2020
互联网之父确诊新冠,一代传奇:任谷歌副总裁、NASA 访问科学家
微软为一人收购一公司?破解索尼程序、写黑客小说,看他彪悍的程序人生!在Kubernetes上部署一个简单的、类PaaS的平台,原来这么容易!2020年,这20个大家都认识的加密交易所过得怎么样?你点的每个“在看”,我都认真当成了AI
相关文章:

华为交换机密码恢复
华为交换机密码恢复说明:以下方法将删除原有config文件,使设备恢复到出厂配置。在设备重启时按CtrlB进入BOOT MENU之后,Press Ctrl-B to enter Boot Menu... 5Password : 缺省为空,回车即可1. Download application file to flash…
nginx源码分析--内存对齐处理
1.nginx内存对齐主要是做2件事情: 1) 内存池的内存地址对齐; 2) 长度按照2的幂取整.因为前面结构体已经是对齐了,如果后面的内存池每一小块不是2的幂,那么后面的就不能对齐 2.通用内存对齐理论 内存对齐:数据项只能…

七喜携手AMD,摆脱英特尔“潜规则”
七喜携手AMD,摆脱英特尔“潜规则”<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />最近,在PC市场随着七喜董事副总裁毛骏飙揭发英特尔制定的潜规则,“游戏规则都是英特尔制定的,全…
半小时训练亿级规模知识图谱,亚马逊AI开源知识图谱嵌入表示框架DGL-KE
出品 | AI科技大本营(ID:rgznai100) 知识图谱 (Knowledge Graph)作为一个重要的技术,在近几年里被广泛运用在了信息检索,自然语言处理,以及推荐系统等各种领域。学习知识图谱的嵌入表示 &#x…

数组的各类排序
1 package sort;2 3 /**4 * 数组的各种排序操作5 * Created by liuwei on 16/3/6.6 */7 public class MSort {8 9 /**10 * 直接插入排序11 * 外层一个循环,从第2个元素开始(下标为1),遍历后面的所有元素12 * 内层一个循环,从当前位置position i 开始,每次…
Virtualbox安装使用注意
1.VirtualBox升级到4.3以后不能打开 提示创建 COM 对象失败 应用程序将被中断 解决方案:右键VirtualBox的桌面快捷方式,选择属性,选到兼容性选项卡,勾选“以兼容模式运行这个程序”,下拉框选择Windows Server 2008 …
机器学习项目模板:ML项目的6个基本步骤
来源 | DeepHub IMBA每个机器学习项目都有自己独特的形式。对于每个项目,都可以遵循一组预定义的步骤。尽管没有严格的流程,但是可以提出一个通用模板。准备问题不仅是机器学习,任何项目的第一步都是简单地定义当前的问题。您首先需要了解背景…

ib_logfile 在数据库中有何作用?
ib_logfile 在数据库中有何作用? ib_logfile0/ib_logfile1 文件在数据库中起什么作用? 如果被删除,对数据库有何影响? ----->>>>>>>>>>> 回复 #1 mugua_xinli 的帖子 用于存放InnoDB引擎的事…

Podfile 常见语法
source URL : 指定镜像仓库的源 platform : ios, 6.0 : 指定所支持系统和最低版本 inhibit_all_warnings! :屏蔽所有warning workspace 项目空间名: 指定项目空间名 xcodeproj 工程文件名:指定xcodeproj工程文件名 …

今天学完了ccna
通过10天的学习,终于学完了NA,但是会不会呢?还是个未知数,再就也一知半解的。觉得基础知识太差了,可是看书,又觉得太长了,太多了,晚上老是停电 白天啥也看不进去。热。还是静不下心&…
攀登数据科学家和数据工程师之间的隔墙
来源 | 数据派 THU机器学习的教育和研究重点往往集中在数据科学过程的模型构建、训练、测试和优化等方面。要使这些模型投入使用,需要一套工程专长和组织结构,对于其中的标准尚不存在。有一个架构可以指导数据科学和工程团队相互协作,从而将机…

js变量以及其作用域详解
2019独角兽企业重金招聘Python工程师标准>>> 一、变量的类型 Javascript和Java、C这些语言不同,它是一种无类型、弱检测的语言。它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变…
在A*寻路中使用二叉堆
在A*寻路中使用二叉堆 作者:Patrick Lester(2003年4月11日更新) 译者:Panic 2005年3月28日 译者序: 这一篇文章,是“A* Pathfinding for Beginners.”,也就是我翻译的另一篇文章A*寻路初探…
“Hey Siri” 背后的黑科技大揭秘!
作者 | Vishant Batta译者 | 苏本如,责编 | 伍杏玲出品 | CSDN(ID:CSDNnews)以下是译文: 如今苹果手机可随时检测并回答“Hey Siri”命令,有人可能会想,它是不是在随时记录我们的日常生活对话呢…

[ASP.NET4之旅]Circular file references are not allowed
将ASP.NET 2.0的项目升级到ASP.NET 4后,用VS2010编译站点,某些控件出现编译错误“Circular file references are not allowed”,比如: <% Control Language"C#"ClassName"NewsRight"%>解决方法…

IOS-XMPP
一、即时通讯技术简介 即时通讯技术(IM -- Instant Messaging)支持用户在线实时交谈。如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈的内容有许多的IM系统,如AO…

libcurl使用
官网:http://curl.haxx.se/libcurl/c/libcurl-tutorial.html #curl-config --libs 得到 -lcurl #cc libcurl_test.c -o libcurl_test -lcurl 所有的例子:http://curl.haxx.se/libcurl/c/example.html 例子: /***********************…

RH5.4下samba共享配置实例(3)
一、基于用户名的访问控制实例: 王乾大哥写的比较详细了,我是跟着他的教程学习的,按照他的教程走一边; 要求如下: 1、创建一个公共的交换文件夹,所有人都可以写入删除,但不能删除修改其他人的文…

《评人工智能如何走向新阶段》后记(再续21)
346.中国抗疫十大黑科技(以人工智能为主力的黑科技) 摘自数邦客(2020.3.30发布) 负压救护车 人工智能机器人:如送餐机器人、消毒机器人、服务型机器人,及机器人呼叫等呼吸道病毒核配检测试剂盒…

nagios npc安装后状态为off的解决方法
1、检查ndo2db的进程是不是二个 nagios 16825 0.0 0.1 6784 396 ? Ss 19:05 0:00 /usr/local/nagios/bin/ndo2db -c /usr/l nagios 17032 0.0 0.3 6784 1268 ? S 19:09 0:00 /usr/local/nagios/bin/ndo2db -c 2、检查nagios.log日志看…
C语言extern关键字定义外部变量--Redis源码extern使用
在Redis2.8中有networking.c,这个文件没有networking.h networking.c首先引入redis.h这个头文件 #include "redis.h" 在redis.c一开始就声明了全局变量 /* Global vars */ struct redisServer server; networking.c的createClient函数 redisClient *cr…
深度学习面试必备的25个问题
作者 | Tomer Amit译者 | 弯月,编辑 | 屠敏出品 | CSDN(ID:CSDNnews)在本文中,我将分享有关深度学习的25个问题,希望能够帮助你为面试做好准备。1.为什么必须在神经网络中引入非线性?答…

一分钟了解阿里云产品:先知计划
一、 概述 阿里云发布了各种各样的产品,今天让我们一起来了解下阿里云先知计划吧。 什么是先知计划呢? 先知计划是一个帮助企业建立私有应急响应中心的平台(帮助企业收集漏洞信息)。企业加入先知计划后,可…

C语言的HashTable简单实现
原文地址:http://blog.csdn.net/zmxiangde_88/article/details/8025541 HashTable是在实际应用中很重要的一个结构,下面讨论一个简单的实现,虽然简单,但是该有的部分都还是有的。 一,访问接口 创建一个hashtable. h…
GitHub标星2000+,如何用30天啃完TensorFlow2.0?
作者 | 梁云1991来源 | Python与算法之美(ID:Python_Ai_Road)天下苦tensorflow久矣!尽管tensorflow2.0宣称已经为改善用户体验做出了巨大的改进,really easy to use,但大家学得并不轻松。tensorflow2.0官方文档和tenso…

【Struts2学习笔记(1)】Struts2中Action名称的搜索顺序和多个Action共享一个视图--全局result配置...
一、Action名称的搜索顺序 1.获得请求路径的URI,比如url是:http://server/struts2/path1/path2/path3/test.action 2.首先寻找namespace为/path1/path2/path3的package,假设不存在这个package则运行步骤3;假…
大话卷积神经网络CNN,小白也能看懂的深度学习算法教程,全程干货建议收藏!...
来源 | 程序员管小亮本文创作的主要目的,是对时下最火最流行的深度学习算法的基础知识做一个简介,作者看过许多教程,感觉对小白不是特别友好,尤其是在踩过好多坑之后,于是便有了写这篇文章的想法。由于文章较长&#x…
频繁分配释放内存导致的性能问题的分析--brk和mmap的实现
现象1 压力测试过程中,发现被测对象性能不够理想,具体表现为: 进程的系统态CPU消耗20,用户态CPU消耗10,系统idle大约70 2 用ps -o majflt,minflt -C program命令查看,发现majflt每秒增量为0&…

Linux 服务器日志文件查找技巧精粹
用来在日志文件里搜索特定活动事件的工具不下几十种,本文将介绍搜索日志文件时应该采取的策略。然后,通过几个具体示例介绍一些使用grep命令手动搜索日志文件的办法。接下来,我们将看到 logwatch工具和logsurfer工具的用法。最后,…