以下内容根据演讲嘉宾现场视频以及PPT整理而成。
本次分享的内容将主要围绕以下四个部分:
一、映客直播发展历程
二、直播遇上云数据库
三、风口上的数据库架构变迁
四、直播典型应用场景分析
一、映客直播发展历程
二、直播遇上云数据库
业务起步:映客APP发布
接下来为大家介绍映客直播从开始到现在的架构发展演变过程。当映客APP刚发布的时候,整个后台其实只有三个人负责,两个开发和一个运维,这时的架构如下图所示。起初的架构其实是非常简单的,后台是由8台虚拟机搭建而成的,其中的6台虚拟机做了服务,而剩下的2台做了存储,存储这部分则是使用了自己搭建的MySQL和Redis。在这个起步阶段,对于后台系统要求最高的一点就是当出现了产品想法就需要尽快地实现,这样的架构非常适合在业务起步阶段的需求条件下实现一个直播APP,当时第一版本的开发工作只花费了2周的时间。
业务发展:规模化
而随着映客直播业务量的提升,从2015年的5月份到10月份,映客的DAU达到了10万+,到12月份的时候就已经达到了100万+,此时的业务发展已经达到了规模化的阶段,这个阶段的整体服务端的架构设计如下图所示。此时的架构也是分为了接入层、业务层、基础层以及数据层,但是此时的架构与第一版的架构相比,其整体的框架已经基本成型了,这一版的架构实现了一些业务拆分、数据拆分以及模块化复用,此时服务的底层仍旧是依赖于Redis和MySQL数据库的。这个阶段最为显著的变化就是引入了云,也就是说此时的服务已经上云了。
对于映客的服务上云,当时的考虑主要基于以下几点:
- DDoS,因为云主机本身是可以防止DDoS攻击的,这样就可以将代理层全部都部署到云上。
- 直播存在一个天然的属性就是有很多的明星活动以及其他大V的活动,因为这些活动所造成的瞬时压力是非常大的,如果使用自建机房就需要为这些可能仅仅持续几个小时的活动而囤积很多台服务器,需要购买很多预留资源。而使用在云之后,云主机本身是按照使用量进行收费的,这样可以将很多核心业务都部署到云上,在出现瞬时活动需要进行扩容的时候就可以直接进行扩容,当活动结束之后就可以释放这些多余的资源,通过这样的弹性伸缩可以极大地降低直播平台的运营成本。
- 云主机以及云数据库等这些云资源使用的都采用的是集群模式的部署,而其集群模式往往也是对于用户透明的,这样就可以理解成云本身帮助我们实现了一层高可用。
- 平滑可伸缩,比如现在的数据库的配置或者性能不能满足需求了,就可以使用云上的这些资源进行平滑地扩容,并且云上的扩容对于服务是没有任何影响的,而且包括SLB负载均衡器这些对于云的用户而言都是比较友好的。
综合以上四点的考虑,映客直播在业务规模化的阶段就使用了云服务。
而使用云服务之后首先需要面对的一个问题就是:整体迁移。对于整体迁移而言,云服务本身也提供了一些工具可以实现对于存储进行实时地同步以及在最后进行切换,对于云服务本身可以实现隔离以及制作镜像之后就可以打包发布到云上去。映客直播当时的业务量也不是太大,所以整体而言迁移上云的过程还是比较顺利的。但是任何事情可能都不只会有好的一面,当使用了云服务之后同时也会遇到一些问题,映客在上云的过程中也遇到了一些不可控的因素,也就是“水土不服”。比如当时的云服务的MySQL连接数是有上限为2000的限制的,而映客当时采用的很多服务框架都是属于多进程的框架,这样就非常容易造成连接数不够用的情况;并且当时外网带宽限制是200M,很容易就跑满了,而且内网带宽也是一样的情况;另外,在使用云主机的时候也会出现一些资源抢占或者宕机的情况。综上所述,在上云之后有好的一面,也存在着不是特别舒服的一面。在这个过程中,映客不再仅仅是一个云服务的用户了,也演变成为云服务的产品经理或者QA,映客与阿里云也是从开始的接触、了解到后来的“相爱相杀”,并且一起来推进云服务的优化,一直到双方都达到比较好的状态。
业务爆发:千万日活
其实云服务本身是作为基础设施的,它可以为我们提供高质量的运维。但是当业务的日活、流量还在爆发性增长的时候,单单依靠云服务这种基础设施的能力还是不够的,所以映客的服务框架也在不断地迭代中。如下图所示的架构框架是在映客上云之后,进行了一次比较大的改造之后的框架,这个框架就已经实现了一些分层,主要分为了用户层、应用层以及数据层,并且在云服务基础设施上实现了很多服务化的重构、存储的优化等的一些技术中间件,做了方方面面的工作来保障当业务爆发达到千万日活的时候,服务还依旧能够支撑住,这样的框架本身的稳定性也还是比较不错的。近期,映客在做的一件事情就是在目前体量已经非常大的情况下,如何去保证资源的独占和安全,目前也正在基于云服务设施进行VPC的部署,而且这项工作目前推进得也还不错。
云上架构
其实大家可以看到,映客的整体架构是构建在云服务基础设施之上的。目前映客已经达到今天千万日活这样的体量还在使用云服务其实主要基于以下几个方面的考虑:首先,我们认为在现阶段,云服务的发展已经相对比较成熟了,并且也是比较安全的,云服务在内部可以保障一些高可用的支撑;另外,用户使用的所有服务基本上都是集群化的,并且是支持平滑伸缩的,这些对于有活动运营需求的直播平台而言都是非常有价值的;并且云服务的用户也不需要预留太多资源来支撑可伸缩的容量;除此之外,如果使用自建机房,那么运维团队需要足够了解每一个环节,需要能够支撑从硬件设施到监控以及上线等各个方面,这对于一个快速迭代的公司的运维团队而言则是非常困难的,而使用云服务则可以保障基础设施的高质量运维。以上这些就是映客直播到目前千万日活的体量依旧选择在云上架构未来的很重要的原因。
三、风口上的数据库架构变迁
接下来为大家分享映客从0到千万日活过程中数据库架构变迁的历程。谈到数据库,无论是像Oracle、MySQL这样的关系型数据库,还是像MongoDB这样的NoSQL的数据库,大家想到的第一点就是数据库的性能。而数据库主机的性能主要和以下的这几个方面相关:CPU、存储、索引、IO、锁、内存以及内部的线程模型等,这些都是确保数据库设计本身性能非常关键的方面。
在数据库架构演变过程中,无论是MySQL、Redis还是MongoDB这些数据库层面的服务都经历如下图所示的变化,从单主机的模式到后来独立主机,到后来的主从读写分离,再后来根据用户、房间、资料等维度进行垂直拆分,而在维度已经很大比如像关系数据已经到达千亿量级的时候还进行了水平拆分。
关键技术点-数据迁移工具
在数据库架构演变过程中涉及到一些技术点,在这里可以与大家分享一下。在数据迁移工具这部分在数据库架构演变过程一直都扮演者极为重要的角色。对于同构数据的迁移而言,其实有比较成熟的方案,同构数据迁移相当于上图中的从单主机一直到垂直拆分这部分,这部分由于所涉及到数据表的结构以及数据的拆分策略都没有什么变化,所以这部分工作直接依赖云数据库的迁移工具,就可以实现数据的平滑迁移,并且业务上基本是无感知的。这部分适用的场景就是服务器级别、实例级别的扩容或者读写分离以及业务的垂直拆分等。但是当体量已经足够大到需要做很多水平层面的拆分的时候,很多现有的成熟的工具就已经不太适用了。这个过程中,映客直播的技术团队就基于binlog等日志层面的东西开发了自己的一套异构数据迁移中间件,这个中间件比较适用于异构数据库或者是做分库分表的迁移。因为在分库分表的过程中要想做到业务的尽量的无感知还是比较困难的,特别是在一开始是单库单表,需要分成1000张表,在分完成1000张表之后是很难再回退过去的,这个成本是非常大的。如果在这个过程中异构数据迁移组件做的足够好,就可以将风险降到很低。
关键技术点-分库分表中间件
第二个关键技术点就涉及到访问分库分表数据的问题。在实现这部分时,我们也调研了很多业界的方案。目前业界比较成熟的方案主要有两种,分别是基于Client的和基于Proxy的,映客技术团队对于这两种方案在不同的时期也都实现过,但是总的宗旨是实现分库分表的透明化。首先,对于业务而言,不需要关心SQL到底执行到哪一个库表上,也不需要关心分库分表的策略是什么。第二个就是数据库本身配置的统一管理,这部分就是对于线上数据的统一切换以及配置都是非常有用的。第三个就是需要提供统一的监控。第四点,既然使用了这个分库分表中间件,就相当于所有的业务都是依赖于这个中间件的,其高可用设计就是非常关键的。另外,分库分表中间件的设计本身是一个集群模式,所以需要做好中间件和数据库中间链接的管理,通过一些连接池的模型将链接更好的管理起来。包括后面的负载均衡以及更好的扩展能力等都是在实现分库分表中间件时需要考虑的。
关键技术点-分布式事务
第三个关键技术点就是分布式事务,在之前可能所有的业务在一个数据库上通过一个本地事务就可以解决问题。而现在已经按照水平拆分和垂直拆分之后分成了很多个库表以及很多个维度的模块,这时候就涉及到了数据一致性的管理。而在这一方面,从业务层面来说业务可能处理的比较多的有两种分布式事务,第一类就是预占资源型,预占资源型就是比如是A要给B送礼或者A给B转账的时候,对于A而言需要扣钱,这部分是需要预先将钱扣掉的,然后再给B加上,这个过程对于A而言就是预占资源型。预占资源型有什么特点呢?其实就是如果想要给B加钱,那么就一定需要确保A的钱已经被扣掉了,而且这个操作如果在最终没有成功,那么对于A而言是非常容易回滚的。相当于预占资源型的分布式事务的要求是实时的、同步的、并且能够保证可回滚。这一部分现在业界使用的比较多的模型就是基于补偿的,也就是tcc的分布式事务框架,这种框架模型也是电商以及金融相关的业务中使用的比较多的。
以上这些就是在实现了数据库架构演变之后,映客技术团队在分布式事务这部分所面临的问题以及所做的事情。
四、直播典型应用场景分析
任何脱离了实际应用场景的架构都很难说它是一个好的架构,所以还是需要去分析架构的应用场景,根据其应用场景来分析究竟应该选择什么样的架构模型。接下来就与大家分享在直播这个应用场景之下,与数据库相关的技术点以及如何进行数据库架构的设计和迭代。
下图中展现的是一个直播大V,直播大V的特点就是其粉丝会非常多,下图中的大V有156万粉丝,而最多的粉丝量可能会达到千万级别。而粉丝量比较多所带来的问题就是无论是推送量还是关注度,还是在直播间中的活跃度都会非常高。而且本身而言,大V的直播也会比较频繁。此时对于平台考验最大的就是关系系统,所以关系系统必须能够支撑高并发、大容量,并且对于关系系统的实时性以及一致性的要求也是比较高的。如果A关注了B,而到最后没有关注成功或者并没有收到B直播的推送信息,那么这就是一个故障。所以这对于关系系统的压力是非常大的,因为任意用户之间都可以建立相互的关系本身就是笛卡尔积的形式。
通过下图大家可以看到,在关系系统的主关系服务上有很多异步化的优化。首先,要想实现这些优化需要确保关系服务本身以及关系数据本身是收拢的,有统一的入口。在这之后就可以统一地把控这个入口,然后确保关键路径写成功,其他非关键路径都可以通过消息队列分发出去,并组建一些异构的数据源或者不同类型的需要做很多Cache优化、异构数据构建等的工作。
下图展现的也是映客平台的一个大主播,在日榜中,这个主播一天收获到了四千多万的映票,而一个映票相当于一毛钱。每个用户可以一个小礼物、一个映票地去送,并且可以连送。这样就会造成这一个问题,因为这四千多万的映票在一天之内,甚至在一个小时或者半个小时内都送给这个主播,势必会对于数据库造成很大的压力,如果主播的数据在数据库中仅为一条数据,那么会涉及到很多次更新操作。所以基于这样送礼的高并发场景,映客也做了很多层面的优化,首先支撑送礼这个场景的金融属性中的强一致性,虽然一个映票只有一毛钱,礼物的价值虽小但是仍旧是一个金融属性,如果这一毛钱没有到主播账户上,这将会成为一个金融故障,其影响将会是非常大的。而且粉丝无论在什么时候送给主播一个映票,都需要看到主播的映票数量是在实时地增长的,如果在短时间内主播的映票数没有增长,用户可能就来投诉了,所以在这个场景下对于实时性的要求也是非常高的。除了需要保证金融数据的强一致性以及实时性的前提,还需要保证在多个粉丝同时向主播送礼时的高并发特性,这对于金币系统的压力也是非常大的。
映客直播金币系统
映客的金币系统在初始时的架构如下图所示,也是依赖于RDS的MySQL集群,一开始是单主机的,后来进行了独立实例的优化,在这之后还进行了读写的分离,实现了读写分离之后其实业务包括送礼、支付和体现还是可以直接操作数据库的。这个时候即便是金币数据库能够支撑的量再大,稳定性再高,当遇到刚才提到的主播一天收到四千万映票的情况时,数据库所产生的延迟也是无法接受的。
送礼逻辑解析
这里为大家分享一个业务中比较核心的送礼逻辑。之前也提到送礼操作和收礼操作需要分为两块,并且每个部分需要采用不同的策略,一种是分库分表的策略,另外一种是使用异步化的策略来解决。
总结
其实,数据库本身而言是一个基础设施。那么作为基础设施,我们主要可以依赖数据库的稳定性以及基本的性能。而云为数据库提供了专家级的运维,这一点也是比较好的方面。但是云数据库也不是万能的,在前面提到的场景中的很多情况下必须在架构层面以及具体的业务场景层面进行具体的架构梳理和优化。在数据库架构方面,我们一直都在路上,并且将会一直努力前行。