数据是创立Asana的核心部分,并且每一个团队都依赖他们自己的方式。我们的负责增长的团队依靠事件数据来分析试验结果(对比试验)。 我们做很多快速的实验--通常会有很多实验一起跑-- 让这些互相影响的作用和其他关键度量引导我们需要放弃什么和投入什么 项目经理,设计师和产品工程师通过分析使用数据来发现不可避免的妥协,比如简洁性对强大性。
通过这种方法,我们可以知道什么样的新产品方向能够释放出最多的潜力。市场部门需要明确在他们的竞争力中的哪个部分能够驱使新用户到Asana。财会部门需要非常可靠的关于总体增长模式的统计数据来帮助Asana确认能持续发展到2064年。你是怎样建造一个支持所有这些多样需求的系统呢 ?
(Asana 数据基础架构)
上图并不是我们一开始就建立的系统。我们从一个十分简单的系统开始,也就是一些python脚本和MySQL数据库,它们全都运行在一个机器上。刚开始的时候,一个简洁的系统能够减少系统维护,并且如果还没有任何用户,或许你就可以从这里开始。但是,从2011开始,Asana的增长就一直稳定(看下面的图)。然后我们就开始碰到一些限制。最近,针对数据基础架构,我们做了一系列的变化。所有的一切都证明是很有价值的。
往监控,测试和自动化上投资来减少救火的次数
从MySQL迁移到Redshift,得到一个可扩展的数据仓库
从本地的日志处理迁移到基于Hadoop的可扩展的日志处理
引进商业智库工具来允许非专家来回答他们自己的数据问题
Asana随着时间变化时的“时间”数量图。按照原始数据量做单位
一年前,我们遇到了一些关于数据处理健壮性的问题。当图表中有个重要的变化,人们立马会质疑数据的整体性。把问题和有趣的想法区分开来是很难的。数据科学已经是一门艺术,所以你需要基础架构来给你提出的问题一个信得过的答案。然而,99%的准确性还是不够好。在数据基础架构小组那里,我们花费了太多时间鼓捣非常紧急的问题,而且这点使得我们没法取得更长期的发展。这太痛苦了。
当坏的事情发生后,我们会采取“5个为什么”的方法来发现问题的原因和解决这个问题。比如,我们曾经让一个数据处理脚本错误地生成了一个超级大的日志文件,它太大了,以至于我们无法用电子邮件发送。作为解决方案,我们在发生日志文件前就开始把日志文件分割成小段,并且在发送邮件错误的时候发送警告信息和在脚本输出结果上增加监控。在其他的一些我们还没有办法洞悉原因的例子里,我们就增加日志,检测和预警。例如,我们的实验总是经常性的落后,所以我们在不同的处理阶段增加更广泛的日志记录来看看哪里花费了最多的时间,并且用来指示什么部分需要优化。
当我们的监控和日志记录不够的时候,最坏的事情持续了好几个月。一个比较极端的例子就是,我们的一个工具花费了比其应花费时间多很多的时间。一段时间后,我们发现了一些查询被传递进了一个不知道为什么我们也没搞懂的、含有有特殊时区信息的时间类。这些查询显著地增加了查询时间。由于这个任务花费了一天多的时间来完成,所以第二天的任务才能接着开始,然而这导致了MySQL锁过期。当生成图像的时候,这些任务就没法取得所有需要的数据。我们隐藏了零数值,并且必须要每次人工地做很多工作去清理。错误总是导致更多的错误,所以打补丁也没有用。最终,这个事件使得我们真正要去把测试的优先级提到最高。
一年前,我们的数据基础架构的代码上面几乎就没有任何测试。然而我们还不能满足我们当前的测试覆盖率,但是我们已经做了很多改进。当你得到一个失败的测试结果并且你意识到这个本可能出问题的部分使得你改变了产品的一些代码。这样的感觉好极了。虽然我们一直在探索节点增加的特性,我们还是使用python内置的单元测试模块。我们把努力的方向放在为数不多的,特别是在那些我们能够建立自己的架构代码的领域,从而使得我们的数据科学家和其他的数据用户能够写出他们自己的测试。
原来我们用cron来运行所有的事情。任务会在不同的时间段运行,我们期望某些任务在另外一些依赖它们的任务开始前完成。但是事情不总是这样。比如,一个任务运行失败,那就需要很多人为的清理。接着,我们开始使用Luigi 来建立一个管道。这个管道懂得依赖性,就像你看到的下图中我们的管道的一小部分示例。通过Luigi,当一个任务运行失败,我们会得到告警,而且所有依靠它的任务都不会运行,直到我们修复那个运行失败的问题。只需要恢复管道并且让未完成的任务继续,这样就简单多了。这个也是我们并行化这些任务的第一步。
我们的过去的预警方式很粗糙简陋。我们有显而易见的比如关于可用的硬盘空间的预警,但是这个花费很多思考和努力来克服困难从而得到我们今天拥有的一切。现在,我们覆盖了所有的系统警告,从内存和CPU使用率到Redshift集群上长时间的高负载。我们监控我们数据管道的变化,当时间花费超出预期或者一些任务没有能够在我们期望的时间内完成时就发出预警。我们监控数据本身,保证重要的变量都是非零的,并且用回归分析来提示一个事件出现多于或者少于在过去的几个星期中我们看到的次数。
(用Luigi画的我们数据的ETL 管道)
我们改进关于优先处理邮件警示的过程。我们十分重度地依赖Asana,它工作十分良好,特别是在分担责任和当数据会出现预知的错误时通知用户。
(原文此处的will应该为with)有了这些努力,问题逐渐变得少了。一旦不再花费时间让已有的数据基础架构发生瘫痪,我们就有时间来建造未来。
我们的数据基础架构的最新发展如下:
最初,我们使用MySQL数据库作为数据仓库,因为我们的工程师擅长优化这个数据库。但是,因为MySQL是基于行记录的,所以它不适合在非常大的数据集合上运行包含复杂链接操作的聚集查询。当我们遇到了性能问题,我们修改索引。当我们还遇到更多的性能问题,我们在MySQL之上建立一个定制的、面向直方图的查询缓冲层。
依旧,每一处优化只能帮助我们走得这么远,并且我们并不想把我们的宝贵的工程师资源花在建立分析数据库上。很多公司都宣称Redshift帮助他们很好的提速。所以我们也打算试一试。结果太好了。在最极端的情况下,一个日常的查询在MySQL上需要6个小时,但是在Redshift上,只需要几秒钟,而且不需要任何修改。
一个在MySQL上需要花费数分钟的查询,但在Redshift只需要1秒钟。
迁移到Redshfit可不是一个小事情。我们已存在的数据管道是适合于MySQL的计划而建造的。并且每一个人都很熟悉这个特点。我们努力抽象出Redshift的特性。比如,通过亚马逊的S3加载数据和依据主键合成数据到一个已有的表格。缺少对于主键的支持是意料之外的最大缺点。然后迁移我们已存在的数据管道的乐趣就开始了。复杂的依赖性意味着我们必须小心地按照正确的顺序迁移写入。有时,当我们迁移从MySQL的一个表格到Redshift的所有查询时,我们必须同时写入到MySQL和Redshift。最困难的部分是协调部门之间的努力去迁移数量巨大的、相互依赖的MySQL查询语句。而且其中的一些只被很少的一部分人理解和使用。我们从数据科学家和商业团队中得到了关于他们最棘手的部分的有价值的反馈。继而,我们使得他们的工作变得更愉快。
然而我们选择Redshift时的主要目的是解决性能和可扩展性的问题,不过它顺便也改进了可访问性。这点来得有点间接和意外。在迁移到Redshift的同时,我们也在探寻商业智能工具。我们评估了一些工具,本来最喜欢Looker,而且决定尝试一下。不幸的是,当我们把它和MySQL连在一起时的分析结果太慢了,以至于我们没法推荐给我们的商业团队。把Looker和Redshift链接后,性能从需要数分钟变得足以实时地在绝大多数查询上循环。这个组合太强大了,以至于我们的商业团队自己就决定用它了。
我们绝大多数的商业团队就凭他们自己,其中有些成员甚至连SQL查询不熟悉,也能够玩数据。更好的是,他们能够在不需要数据基础架构小组的支持下做到这点。他们的团队负责人说:“这个就仿佛我把1995年自动挡的吉普牧马人换成了法拉利一样爽… 有快又有乐趣!”
Redshift还提供了工具用来限制给单独的进程和程序的资源。我们非常依靠这些功能来防止某些个人把数据库独占,从而别人无法使用。通过增加机器的数量,然后按一些按钮我们就能在半个小时内加速和增加存储量。在将来,我们还可能自动化这个过程。
我们日常的数据处理延迟变得很长,但是我们努力保持处理时间在24小时内。虽然Redshift起了很大的帮助,但是我们也需要扩展日志处理部分。我们决定采用这个行业的长期标准 Hadoop MapReduce。除了容易变得可扩展的,这也是一个更容易的数据处理方式。和建造易使用框架的努力一起,这个使得更多的每天工作不是写代码的同事也能够把日志处理成有用的模式。因此,这个既是一个大的扩展性项目也是一个易用性的项目。
我们在Yelp的映射归纳任务框架(mrjob)的基础上建立我们的系统。因为我们都知道Python很好,而且在灵活的MapReduce上开始跑任务也比较容易。我们知道这个明显地比Java和流慢一些,但是那个层次的性能还不重要到让我们降低易用性。我们在设计基础架构的时候就好像知道在将来我们会把mrjob换到到其他的一些东西。
当我们开始用MapReduce的时候,我们仍旧同时写入MySQL和Redshift中。起初,这个让我们同时从Hadoop集群上加载数据到两个数据库中。但是这个并不好使,因为大多数的集群会空闲很长的时间,而有时我们就很容易地碰到过期。所以我们提倡放弃MySQL,而在集群之外,移动数据到Redshift。亚马逊的弹性MapReduce可以存储输出到S3。我们利用这个来存储数据,并且加载它到Redshift上来作为一个来自单独的服务器的任务。
当前,我们用一个八个节点的集群,这个给我们4到6倍的性能提升。当我们负责增长的团队要增加三倍的运行任务的时候,我们只需要增加Hadoop集群的大小或者增加更多的集群。我们运行在亚马逊弹性MapReduce上,就使得这样做变得更容易。可扩展性还间接地帮助了易用性。因为不用担心他们的代码变得很慢和对数据管道有负面的影响,我们的商业团队在增加更多的数据处理上变得舒服很多。
当调研商业智库工具的时候,有人介绍Interana。一个基于交互事件的、处理原生日志文件的分析解决方案。然而,这个并不是我们一开始需求的东西。我们集合我们的数据后发现它可以满足一个之前并没有预料到的需求:超快循环分析原生日志。我们就成为他们的最初的几个用户之一。在早期的产品设计里,我们和他们反复交流,使得他们实现了很多我们的性能需求。这逐渐地成为我们产品团队数据分析中的一个集成部分。同时,Looker继续成为我们商业团队的一个重要的补充。我们的团队需要及时分析某几个时间点上数据的状态。
我们能够在几秒钟内处理十亿数量级的数据点。从而展现出很多我们的数据中深层次的数据分析,这在以前不可能的。任何查询数据模式的人都能够很快地切割数据来发现根本原因并且拥有我们全部的数据集的访问权来快速地在区块中筛查。这允许他们探索我们的用户怎样使用这个产品,从通过群组来做简单的事件计数到复杂的对话和漏斗分析。现在,我们很少写专门的脚本来扒下创建特殊聚集的日志。我们开始用Interana来分析性能日志。团队成员说:“一旦当Interana加入到我们的数据处理管道中,查找和解决回归分析的效率就提高了一个数量级。”
一些Looker擅长的例子:
查询金融和收入数据;多种方式分切收入来理解增长的趋势
视觉化随着时间流逝的群效应(见截图右侧部分)
数据堆砌;所有满足一个标准的客户,等等。
(Looker帮助我们查看大维度建模在时间轴上的群效应)
一些Interana 擅长的事情:
交互的漏斗分析
视觉化用户行为,导致新能问题(截图中的右边部分)
理解长期使用这个应用的用户会做什么操作
Interana使我们能够找出在Asana中最慢的一些共同的行为
除了这些大项目,我们加固了一切,从而使得同事不会轻易的不小心弄瘫痪设备。Justin Krause,我们的商业智库负责人说:“我们的工作生活变得非常好了,我几乎不会弄坏任何东西了。” 大多数星期里,我们只用半个小时的时间来维护基础设备。我们喜欢我们现在的状态,但是这个仅仅是漫长旅行中的一点。伴随增长,新的功能,新的生意需求,我们管道中的很多部分在将来的岁月中都会变得过时。我们知道事物总是会出现新的、有趣的错误,所以我们也增加测试和监控,以谋求在发生前发现大部分情况。我们还留意在数据分析领域中,哪个新系统变得流行,我们就会做出相应的对策。
我们认为会在下面几点探索一下:
加入Hive,在Redshift之上增加一些东西,或者在Interana的能力范围之外用另外一个系统来做原始的日志查询。
流数据分析的系统
比mrjob更快的Hadoop,或者可能用像Spark一样的东西来做内存中的MapReduce
更好的异常探测和趋势预警
限制单点缺陷
如果你对在快速变化的环境下建立数据基础架构有很好的想法,请加入我们下一阶段的旅行吧。如果你想分析大数据和学习各个组之间怎样工作,就以一个数据科学家的身份来用这个基础架构!Clark Bernier,我们的一个数据科学家说:“和一群有天赋,有担当的数据基础架构团队一起工作是在Asana中作为数据科学家时最美好的一部分。我能够专心于数字和他们的含义中,我相信我的分析能够如闪电般一样飞速。”
来源:董老师在硅谷 知乎专栏
原作者:Marco Gallotta
译者: Liang Yu
本文来自云栖社区合作伙伴"DBAplus",原文发布时间:2016-04-04