数据驱动 x 敏捷开发,字节是如何践行这两大技术理念的
如果说推荐算法、大数据技术是支撑字节跳动业务发展的技术能力,那么其迭代创新的核心技术理念又是什么?
10月27,在「稀土开发者大会」上,火山引擎总经理谭待以《数据驱动x敏捷开发,业务高速增长的双引擎》为主题,深度解密了字节跳动业务快速发展的两大技术理念——数据驱动、敏捷开发,分享如何构建数据驱动的飞轮,以及如何通过全栈云原生架构,支撑大规模应用实现敏捷开发。
以下为谭待的演讲实录:
大家好,我是谭待,是字节跳动火山引擎业务的负责人。很高兴收到稀土开发者大会的邀请,今天能够和大家分享、探讨字节跳动的技术理念和实践。
火山引擎是企业的数字化增长引擎
在开始分享之前,我先向大家介绍一下火山引擎。
火山引擎是字节跳动旗下的企业级技术服务平台,是字节跳动技术团队对外提供技术服务的统一窗口,我们希望通过火山引擎,把字节跳动的技术、产品和服务对外开放,包括云、AI、大数据、推荐等等,来帮助不同行业中的企业实现自身增长和数字化转型。
大家知道,字节跳动内部一直在践行技术中台的技术文化。所以我们在做技术ToB过程中,也采取了这种机制,让技术中台直接实现自身产品的商业化。因此,火山引擎对外开放的技术和工具,与字节跳动技术中台完全同源。比如说推荐,用的就是今日头条、抖音的同款推荐平台、工具和方法论。通过这种方式,我们可以把内部最好的能力对外进行服务。
这是火山引擎整体的产品技术体系,一共分为四层,分别是:统一基础服务、技术中台、智能应用和行业解决方案。这四层从下至上,分别满足企业从运维、研发、产品、运营到营销,在不同行业、不同业务场景下的需求。
这是过去一年里,我们不断把字节跳动内部技术商业化后形成的结果,而在这个过程中我们一直在思考,字节跳动是怎么一步一步发展至今的,这背后支撑着业务快速发展的技术理念是什么?今天我想和大家分享下我的理解,我认为在这个过程中,有两大理念非常重要,分别是:数据驱动、敏捷开发。
数据驱动:构建数据驱动的飞轮
首先和大家聊聊数据驱动。亚马逊有一个著名的飞轮理论:一个公司各个业务模块之间应当有机地组合,相互推动,就像是咬合的齿轮一样。每一个飞轮从静止到转动起来需要花费力气,但是由于他们组合在一起,所以每一圈的转动都不会白费。一旦有一个齿轮转动起来,整个系统都会跟着转动,越转越快。
构建数据驱动的飞轮
回到数据驱动这个话题,我们认为同样如此。数据驱动不是一蹴而就的,不是用了一个工具,或者说建了几张报表就做起来了,而是在整个过程中,不停地去解决一个个问题,最终形成多个体系,让他自动转起来,形成数据的飞轮效应。一旦飞轮效应形成,越到后面转得越快。数据驱动就会成为日常内部协同的习惯,最终成为业务增长的源动力。
围绕这一目标,我们可以把建设飞轮分为四个关键步骤,业务过程数字化、数字化协同、数据驱动业务优化、客观的分析评估。
这几个步骤之间是一个有机推动的过程:
业务过程的数字化是第一步,也是非常关键的一步。业务过程的数字化越充分,对业务的描述就越精准,才能有利于后面步骤的展开。所以,我们需要不断地将离线活动在线化,在线活动精细化,全部通过数字化的方式进行表达。
实现了业务过程的数字化之后,第二步就是数字化协同。第一要通过数据治理等手段让底层数据得到规范、统一的表达。第二是要让更多的人参与进来,所以需要通过数据可视化等工具让不同的角色(开发人员、运营人员、使用人员、管理者等等)使用起来,加入数字化协同的过程。
数字化协同能力,最直接的影响是效率的提升。协同得越好,就能越及时、全面地获取业务的认知,也就能在数据上更客观地支持上层业务的优化。
优化的效果一定不是拍脑袋,也不是凭感觉,而是用客观的分析评估。一方面,可以用A/B测试等方式通过数据来精准评估业务带来的实际收益,另一方面,我们也要进一步多维度的关联原因。
最后,走完这四步后,在业务优化和评估过程中,我们又能沉淀更多的数据,这就形成了闭环,实现了飞轮的转动。
字节的数据驱动飞轮
刚刚是一个偏抽象的描述,下面我们再结合字节跳动的具体情况来看:
业务过程数字化,主要是对于不同触点的数据埋点,比如APP、小程序、运营页等等;
数字化协同,是多角色对数据应用的协同加工。比如研发如何做好数据开发、数据治理,运营更好更快的用好数据等;
数字驱动业务优化,主要是根据数据,根据数据产生的insights,对产品、算法进行优化,比如对推荐系统策略的优化,面向不同用户群体运营的优化等;
客观的分析评估,一方面通过A/B测试,对不同的、新的迭代进行客观评估,另一方面则是通过ABI进一步地进行数据洞察,能够积累对于的insights,从而促进整个流程的转动。
这就是字节跳动构建整个数据驱动飞轮的过程,在这个过程中,我们把“业务过程数字化”、“数字化协同”、“客观的分析评估”这三个沉淀下来,固化成数据中台统一的能力,去支持不同应用的数据优化,同时中台能力,还能对业务不同维度,包括增长、体验、变现等等实现进一步的优化。
下面我们就数据中台和应用优化,进行展开。
面向应用的数据中台
刚才其实也提到了数据中台,它最大的一个作用是帮助各个应用、业务基于数据驱动进行优化。所以做数据中台有一个很重要的理念,那就是一定要面向应用来构建。从数据开始,用数据来做验证。那么谈到数据的验证,那最重要的其实就是A/B测试。之前我们也在不同场合强调过字节对于A/B测试的重视,包括抖音、头条的起名也是通过A/B测试得来的。
对于评估而言,测试只是第一步,我们还需要进一步对结果进行分析,因此构建了相应的数据运营平台、智能数据洞察和客户数据平台等工具,帮助产品和运营可以深入分析数据。
而在底层,面向每天产生的大规模、批量、实时的数据,我们也建设了一套完整的数据采集、研发和治理的套件,提升数据开发的效率。
所以可以说在底层,我们更关注数据开发的效率和规模,而在上层,我们关注的是整个产品和运营在做数据分析过程中的易用性、可交互性。要实现易用性、可交互性和底层规模和效率的一个连接,我们需要一个非常强大的数据分析引擎,那就是我们的ByteHouse。
ByteHouse起源于开源的clickhouse项目,所以有了House的后缀。但它其实是根据字节跳动大规模数据场景,进行了非常多的需求改造,最终形成的一个云原生的大规模数据分析平台。
刚刚提到,数据驱动是字节跳动的重要技术理念,每天我们有数十PB的新增数据,有数万多人要从各种维度各种细节,对这些数据进行分析。这里面就有很多性能问题、实时问题需要解决,背后就是靠ByteHouse支持的。
目前为止,ByteHouse几乎服务于字节内所有的业务线,也是ABI系统、UBA系统、画像系统、A/B测试等分析系统的核心引擎。整体规模达到了三万台服务器,每天查询有几千万次。
面对刚才说的大规模挑战,我们在ByteHouse上主要做了五个层次的深度改造:
第一是支持流式数据。对分析而言,我们对实时性的要求非常高,所以我们通过Kafka支持了对实时数据的处理。这样通过ByteHouse可以实现对实时和离线的数据提供统一的分析平台,支持批流一体。
第二是计算和存储的分离。因为我们的规模实在太大了,如何在数十PB新增数据基础上,支持数万人,高效快速地做千万次的即时查询,是一个很大的挑战。通过计算和存储的分离,我们能更好地解决性能问题。分离之后,计算层可以单独地进行弹性的扩缩容。在存储一块,可以和分布式存储系统进行对接,包括HDFS、S3等等。这样一方面能解决存储的稳定性问题,另一方面也能解决扩容问题。
在计算和存储的分离之外,我们在运维、安全方面做了很多工作,以进一步去弥补社区版本功能的缺失。
最后一个很重要的是我们做了多级的资源隔离。因为每天有不同的部门、角色在做各种各样的分析,那么权限、时效性的要求都不一样。那么通过租户的隔离、读写的分离以及异构的计算资源,就能很好地满足不同部门、不同角色在大规模集中式地使用资源分配的问题。
通过以上这五个大的层次上优化,所以我们能够基于ByteHouse去支撑起整个字节跳动数据驱动里的核心步骤。
应用优化
刚才讲了数据中台的一些实践,接下来再讲讲怎么去通过数据驱动来做应用和业务的优化。这里以增长获客来举例。
当然不管是增长场景还是其他场景,如果要做好数据驱动优化,首先最关键的就是设计好指标体系。因为指标不对,做的再多都是错的。
那么对于增长而言,我们认为最重要的有两个指标——「正向的投入产出」和「健康的用户规模」。
正向的投入产出,简单来说就是ROI>1。看起来非常简单,但怎么把ROI算对、算准以及精细到每个用户粒度跟进长期的 ROI,其实是难点和关键。
当然我们也不能只看短期的ROI,还要看长期的用户的健康度,包括留存,LT等等。
设定了这些关键指标之后,其实就可以通过指标去找到对应的优化增长策略。这个增长策略不仅要满足指标的正向,同时也要具备可持续、可规模化、可复制的模式。这样就把业务的增长模式转化成了可衡量、可跟踪的数据驱动模式。
最后用一张图去完整地阐述数据驱动、基于中台和应用优化,来构建整体飞轮的案例。
首先基于数据做用户定向,定义好目标,找到对产品最关键的人群;
找到之后,去做对应的创意、内容,然后让这些最优质最吸引的内容在不同渠道触达到客户,形成转换并产生新的数据。而且我们有数字化记录的过程,能够准确地归因,精细化地追踪效果;
在优化过程中,会有很多创意。我们通过A/B测试高速迭代,看看哪个创意更合适。而在评估的过程中,也会出现更多的数据,从而又补充了整个策略方案,最终就形成一个数据驱动的增长飞轮。
在这样的过程里面,实验的速度是非常关键的。如果别人一天只能做10个实验,你能做100个,那结果不言而喻。小到创意的实验,大到APP功能的迭代开发,速度在里面都起到非常大的作用。而这就呼应了我想讲的第二个理念,敏捷开发。
敏捷开发:全栈云原生架构支撑大规模应用
说到敏捷开发,我们可以看到市面各种各样不同层次的解决方案,比如说低代码,aPaaS等等。不过今天主要想和大家聊的还是云原生这块,因为无论是SaaS层还是PaaS层的方案,在底层都离不开一整套云原生架构的支持。
字节跳动全栈云原生化架构
这里也简单回顾下云基础技术的发展历史,相信很多人也比较熟悉这段轨迹了。可以看到,13年是一个重要的拐点。13年之后,随着Docker、K8s等技术的兴起和普及,云从以基础设施为中心,走向以应用为中心;从资源服务化走向平台服务化,而字节跳动刚好诞生在2012年,因此非常幸运没有什么历史包袱,直接拥抱了最新的云原生技术。
给大家分享一组数字(2021年2月份统计):字节跳动内部业务中,服务器的节点数近百万;同时在线的微服务数有8w+,并且在以每月2000的数量增长;容器数750w+;每日新增量60多PB。
从这些数字大家也可以看得出,我们面临的是一个非常大规模的,而且还在不断快速上涨的服务体量的挑战。所以从基础架构的视角,我们认为有三个方面的问题需要考虑:
第一是如何支撑海量服务。随着应用微服务化,治理对象由单体应用转变为数量更庞大的微服务,这导致全局治理难度更加大,包括构建全局的配置中心以及更灵活的全局网络、运行时的选择、配备完善的安全机制,以及如何端到端的和整个DevOps流程进行打通。
第二是在大规模调度运维下的挑战,如何让基础设施更加稳定。目前内部平均单集群规模是5000多节点,大的集群有数万台。在这么大体量的情况下,需要考虑各种各样的问题,比如在大规模镜像分发的场景下,怎么做镜像预热、多集群的联邦管理的问题;在弱网环境下,云边协同的问题;在异构的环境下,机器学习的场景里面的GPU调度问题。
第三,是在线/离线的混部。因为这么大的规模,成本自然也很大,所以我们要做好利用率的提升。在线/离线的混部是非常重要的手段。特别是字节跳动业务本身,其实波峰和波谷都很明显。比如抖音高的峰值就在晚上,其他时候的QPS就没有这么高。所以我们设计了一套在线/离线混部的机制,一方面可以降低成本,一方面能够更好地应对极端情况下业务规模增长的难题。
同时,在底层,我们还构建了一个容器+多云的整体解决方案。
在多云方面,我们不仅计算能够做到多云,有状态的存储也能够做到多云,这样我们就能够非常灵活的去应对各种的突发情况,比如年初的春晚抢红包,以及818新潮购物节等等。
这张图从架构体系角度,进一步来阐释全栈云原生的体系结构。
首先在最底层,是一套完整的云原生基础设施。通过统一的底层去提供新一代的高性能计算存储和网络的解决方案,这其实是保证业务稳定和敏捷的基石。
在云原生基础之上是服务平台层,它要解决的是业务开发中的一些通用平台和服务能力的抽象。这里面包含了高性能的微服务框架、基于服务网格的微服务治理能力,以及Serverless、边缘计算平台的能力。服务平台构建就是为了让开发人员更敏捷、专注地开发业务逻辑,而能更少地考虑资源、平台、服务间通信和治理。
在平台层之上是整个研发体系的构建。这一层我们是希望通过各种各样的工具、流程机制和组织,能够去帮字节跳动灵活地支撑全部业务线的快速开发和开发管理工作。
这中间三层设施的两边是重要的云原生安全体系和SRE服务支撑体系。
第一个是云原生安全的体系。那么相比传统的安全体系,它要做到不同层次的延伸,一个是左延,不仅关注运行时的安全,我们也需要和DevOps的流程结合在一起,去关注应用整个生命周期的安全。第二个就是下延,不仅只关注到容器的安全,还要关注到主机的安全。
第二个就是SRE体系,它来支撑整个业务高速发展过程中的稳定性。
因为时间有限,我挑了两个比较有意思的话题来进一步的分享。一个是微服务,一个是移动开发。一方面比较有代表性,另一方面这两者覆盖了大部分业务研发的场景。
服务器端——微服务、服务治理与DevOps
首先来看微服务。我们可以用四个点来形容字节跳动微服务的现状:
规模庞大且增长迅速。刚才介绍过字节跳动现在的微服务数是8万,但在2018年,整个微服务数大概只有7000到8000,所以三年其实翻了近10倍,并且还在不断的增长。在这个过程中,我们自然遇到了非常多的挑战。
在线微服务超过90%都运行在容器里。对于业务线,是看不到资源的,看到的只是PaaS、容器。这带来很多便利性,有利于新技术的核心功能推广,但同时也有很多挑战,尤其是调度复杂性这方面。
技术体系以Golang语言为主。根据最新的调查统计,字节跳动内部Golang是主要语言,超过55%的服务都采用了Golang,排名第二的语言是NodeJS,然后是其他的语言。
Service Mesh的全面落地和应用。字节跳动是国内最早在生产环节大规模使用Service Mesh的公司之一。
大家可以发现整个字节跳动在微服务的使用上是非常快的,甚至可以说是比较激进的。这背后,是因为在字节跳动,速度和效率是我们研发要解决的Top1问题。每天新应用和新用户增长都非常快,研发必须要解决好产能问题。这也是我们激进地采取微服务架构的原因。但这么大的规模下,做这么快的迭代,自然会对稳定性、信任带来非常大的冲击。
为了应对这些困难和矛盾,我们在端到端落地微服务架构时,针对性地做了各项优化:
首先是语言层面,Golang是主力使用的语言,因此在Golang层面做了很多框架层面的优化,比如RPC框架、HTTP框架。这些框架我们已经通过开源的方式回馈到社区——9月初,字节跳动开源CloudWeGo,帮助更多开发者搭建云原生微服务架构。
第二则是针对海量服务的治理,我们基于ServiceMesh的概念构建了自己的服务网格体系,将服务治理的能力固化到字节内部平台上,一方面帮助我们多元多服务的兼容问题,另一方面通过Golang稳定的框架和以Mesh治理为基础的理念,我们实现了全局流量的治理、单元化和体系化的整体建设。
最后是通过落地和实践DevOps工具和方法来提升研发的效率,进一步提升运维的可观测性。
下面我们就一个个展开。
首先是Golang框架这块,一个是Kitex,这是RPC的框架。另一个是Hertz,是HTTP的框架。这些框架背后集成了我们自研的高性能的网络库,去解决网络上的一些性能、交互上的问题。同时我们支持多消息协议(Thrift/Protobuf)和多交互方式(Ping-Pong/Oneway/Streaming),能提供更加灵活自主的代码生成器。
这是Kitex和gRPC性能的对比,我们选了两组,分别是基于Thrift和Protobuf协议的对比。可以看到在两种方式下,Kitex都有比较好的性能表现。特别是在在TP99延迟上,随着并发连接数的增大,Kitex表现出的优势是越来越大。
这是Hertz和业界一些框架的对比,包括平均时延、QPS,以及在不同Size包的情况下的对比结果。这两个框架我们现在都通过开源的方式在对外提供,所以欢迎各位开发者去下载使用,和我们交流,提供意见。
接下来我们看服务网格的治理。刚才谈到过因为本身的业务类型、业务体量,所以我们在实践微服务的架构中,面临着非常多挑战,比如语言碎片化、服务异构、协议异构,还有安全、可观测性、问题追查调用等等。所以我们采取了基于服务网格模式,来进行整体的微服务治理。
上图绿色方框是控制面,虚框是数据面。我们通过服务网格将控制平面和数据平面进行了分离,消除了单点故障的可能。比如当数据平面流量过大出现性能问题时,就不会影响到控制平面的路由策略;反过来也是,当控制平面策略负载过重时也不会影响数据平面的转发。
图中每个虚框是一个pod,与传统的服务相比,我们的服务网格是通过sidecar方式进行流量治理,比如熔断、限流、超时重试、降低等,把这些功能从每个服务中剥离出来形成一个代理,通过这些代理实现服务间的治理。这样的好处是能够让每个服务只关注自己的业务逻辑,不需要管全局的调度和通讯问题,让开发更简单、高效。
当然这种ServiceMesh无侵入性的模式带来了很多便利,但是实际上也带来了很多挑战。最大一个挑战就是额外的性能开销,所以我们做了大量的工作去解决服务网格的极致性能优化。这样的一个优化是多个层次的:
在网络和内核层面,我们用共享内存或者系统调用的方式来实现真正的zero copy。
也会在基础库、组件架构层面的优化,去除一些不必要的交互。甚至在编译阶段,我们通过更好的全静态的编译,不需要任何代码的修改,就能够获得2%左右的性能提升。
最终通过这种整体的、多层次的组合优化,我们既享受到了服务网格带来的便利,也保证了性能。
移动端——极致体验的移动APP研发
刚才讲的是微服务框架和服务治理的内容,接下来我们再来说一说移动开发。
对于字节来说,可以算是一个移动原生的企业,我们绝大部分的业务也都是通过APP在承载的。截止目前,我们已经运营超过100款APP,公司内部也有数千人的移动应用研发团队。
要支撑如此大规模的研发团队和对应业务的发展,我们必须建立一套行业领先的移动应用开发平台,并且要通过大量的实践和各种极端场景的打磨来不断优化。因此我们很早就建立了公司级的移动研发平台,代号:MARS,通过它来统一支撑上层各个业务应用的开发工作。如今大家在用的抖音、头条等APP都是基于MARS进行开发和迭代。
从层次角度,MARS整体可以分为5个板块:
首先是项目管理,通过抽象字节内部的研发特点,我们建立了统一的项目管理平台用于支撑日常业务迭代管理,特别是发版等特殊流程的优化。
其次在应用开发环节,这一步效率是很关键的,我们针对效率采用低代码的方式来进行进一步的提升。比如针对设计人员提供了通过设计直接生成代码的方式。对于运营人员、研发人员,我们采取了这种可见即可得的方式,通过拖拉拽去帮助业务人员能更容易更便捷地构建业务应用。
然后面向传统的编码和研发阶段,我们面向APP、前端以及小程序等不同的端都输出了一套完整的端到端的开发平台。
另外在质量管控,我们也提供了一站式全链路测试平台,基于海量真机真实模拟线上实际场景,最大限度检测潜在异常。
最后是全链路监控平台,能够覆盖“终端-网络-后台应用-基础环境”的完整应用链路监控,帮助研发人员精准定位问题,解决问题。
通过以上对微服务、移动开发平台Mars的介绍,我想大家对字节跳动敏捷开发应该有了一个更生动的认识。
回到今天分享的主题,在整个字节技术发展的背后,数据驱动和敏捷开发是两个重要的理念,但这两个理念并不是割裂的,二者是一体的。因为对于数据驱动而言,我们需要有更多的实验,来找到好的方案进行推广,找到不好的点进行改进。而敏捷开发就能保证每天都有大量的实验能够进行。反过来通过数据驱动,我们又能够去找到里面有价值的东西,同时也能沉淀更多的数据,这样就构建了整个业务高速发展的闭环。
这里也分享一些数据,在字节跳动内部,我们每天新上的实验有1500个,实验总量有80多万个,同时运行的实验有1万多个,覆盖了内部500多个业务线以及各种各样的场景。包括个性化的场景、推送的场景、建站的场景、服务端的场景、广告营销的场景等等。
而我们底层的技术、平台的技术,还有业务层的技术,也正是因为这两个理念在不断的积累和迭代,最终去推动业务的高速发展。
其实道理非常简单,就像大家说天下武功唯快不破一样,道理都是很简单的道理,但是要做好这些事情的背后,我们需要工具平台和方法的不断积累,以及把这些方法形成日常的习惯,最终形成业务推动的原动力。
以上就是我对字节跳动在数据驱动、敏捷开发两方面技术实践的概括与分享。希望对大家有所启发。里面提到的很多技术,基本都在火山引擎上实现了对外产品化,也非常期待大家能使用这些产品,反馈意见,创造更大价值。
谢谢大家!