设为首页 加入收藏

TOP

千万级流量的优化策略实战(四)
2019-09-17 18:20:37 】 浏览:115
Tags:千万 流量 优化 策略 实战
成本。一方面代码库数量增多提高了开发工程师的维护成本,另一方面,部署集群的变多会增加运维工程师的工作量;
  • 代码不共享所导致的重复编码工作。
  • 解决重复编码工作问题的一个思路就是为不同的系统提供共享库(Shared Library),但是这种耦合反过来可能导致部署机器中引入未部署业务的开销。所以在共享库中要减少静态代码的初始化开销,并将类似缓存初始化等工作交给上层系统。总的来说,通过共享库的方式引入的开销可以得到控制。但是对于业务密集型的系统,由于业务往往是高度定制化的,共用一套代码库的好处是开发工程师可以采用Copy-on-write的模式进行开发,需要修改的时候随时拷贝并修改。共享库中应该存放不容易变化的代码,避免使用者频繁升级,所以并不适合这种场景。因此,对于业务密集型的系统,分代码所导致的重复编码量是需要权衡的一个因素。

    垂直分割是一个非常简单而又有效的性能优化模式,特别适用于系统已经出现问题而又需要快速解决的场景。部署层次的分割既安全又有效。需要说明的是部署分割和简单意义上的加机器不是一回事,在大部分情况下,即使不增加机器,仅通过部署分割,系统整体吞吐量和可用性都有可能提升。所以就短期而言,这几乎是一个零成本方案。对于代码层次的分割,开发工程师需要在业务承接效率和系统可用性上面做一些折衷考虑。

    恒变分离模式(Runtime 3NF Pattern)

    原理和动机

    基于性能的设计要求变化的数据和不变的数据分开,这一点和基于面向对象的设计原则相悖。在面向对象的设计中,为了便于对一个对象有整体的把握,紧密相关的数据集合往往被组装进一个类,存储在一个数据库表,即使有部分数据冗余(关于面向对象与性能冲突的讨论网上有很多文章,本文不细讲)。很多系统的主要工作是处理变化的数据,如果变化的数据和不变的数据被紧密组装在一起,系统对变化数据的操作将引入额外的开销。而如果易变数据占总数据比例非常小,这种额外开销将会通过杠杆效应恶化系统性能。分离易变和恒定不变的数据在对象创建、内存管理、网络传输等方面都有助于性能提高。

    恒变分离模式的原理非常类似与数据库设计中的第三范式(3NF):第三范式主要解决的是静态存储中重复存储的问题,而恒变分离模式解决的是系统动态运行时候恒定数据重复创建、传输、存储和处理的问题。按照3NF,如果一个数据表的每一记录都依赖于一些非主属性集合,而这些非主属性集合大量重复出现,那么应该考虑对被依赖的非主属性集合定义一个新的实体(构建一个新的数据表),原数据库的记录依赖于新实体的ID。如此一来数据库重复存储数据量将大大降低。类似的,按照恒变分离模式,对于一个实体,如果系统处理的只是这个实体的少量变化属性,应该将不变的属性定义为一个新实体(运行时的另一个类,数据库中的另一个表),原来实体通过ID来引用新实体,那么原有实体在运行系统中的数据传输、创建、网络开销都会大大降低。

    案例分析

    我们的挑战是提供一个高性能、高一致性要求的团购服务(DealService)。系统存在一些多次请求杠杆反模式问题,客户端一次请求会导致几十次DealService读取请求,每次获取上百个团购详情信息,服务端单机需要支持每秒万次级别的吞吐量。基于需求,系统大体框架设计如下:
    恒变分离模式
    每个DealService定期从持久层同步所有发生变化的deal信息,所有的deal信息保存在内存里面。在最初的设计里面,数据库只有一个数据表DealModelTable,程序里面也只有一个实体类DealModel。由于销量、价格、用户评价等信息的频发变化,为了达到高一致性要求,服务系统每分钟需要从数据库同步几万条记录。随着美团团购数量的增多和用户活跃度的增加,系统出现了三个问题:

    1. 团购服务网卡频繁报警,由于这是高性能低延时服务,又导致了大量的客户端超时异常;
    2. 频繁的full GC,这是由于每条数据库记录更新都会导致运行系统里面老的DealModel实体被销毁,新的DealModels实体被创建;
    3. 数据库从库滞后主库,使得服务数据一致性降低,原因是数据库系统写数据量巨大。

    在对系统进行分析之后,我们采用了如下措施,大大降低了网络传输的数据量,缓解了主从数据库同步压力,使得客户端的超时异常从高峰时候的9%降低到了小于0.01%(低于万分之一):

    1. 将DealModelTable中的销量、价格、用户评价等常变的信息单独构建一张数据表VariableDealModel;
    2. 同时在代码中为销量、价格、用户评价等常变数据创建一个单独的类VariableDealModel;
    3. DealService对两张表进行分别同步;
    4. 如果DealModelTable的记录产生了更新,运行系统销毁老的DealModel实体并创建新的DealModel实体;
    5. 如果只是VariableDealModel的记录产生了更新,只对VariableDealModel的属性进行更改。

    缺点和优点

    采用恒变分离模式,主要有三个缺点:

    1. 不符合面向对象的设计原则。原本概念上统一的实体被切分成多个实体,会给开发工程师带来一些理解上的困难,因此增加维护成本。进一步而言,这会增加引入额外Bug的概率(实际上面向对象之所以如此受欢迎的一个重要原因就是容易理解)。
    2. 增加了类不变量(Class invariant)的维护难度。很多情况下,Class invariant是通过语言所提供的封装(Encapsulation)特性来维护的。当一个类变成多个类,Class invariant可能会被破坏。如果必须维护Class invariant,而这种Class invariant又发生在不同实体之间,那么往往是把不变的属性从不变实体移到易变的实体中去。
    3. 一张数据库表变成多张,也会增加维护成本。

    在如下两种场景下,恒变分离模式所带来的好处有限:

    1. 易变数据导致的操作和传输并不频繁,不是系统主要操作;
    2. 易变数据占整体数据的比例很高,杠杆效应不显著,通过恒变分离模式不能根本性地解决系统性能问题。

    总的来说,恒变分离模式非常容易理解,其应用往往需要满足两个条件:易变数据占整体数据比例很低(比例越低,杠杆效应越大)和易变数据所导致的操作又是系统的主要操作。在该场景下,如果系统性能已经出现问题,牺牲一些可维护性就显得物有所值。

    大部分系统都是由多种类型的数据构成,大多数数据类型的都包含易变、少变和不变的属性。盲目地进行恒变分离会导致系统的复杂度指数级别的增加,系统变得很难维护,所以系统设计者必须在高性能和高维护性之间找到一个平衡点。作者的建议是:对于复杂的业务系统,尽量按照面向对象的原则进行设计,只有在性能出现问题的时候才开始考虑恒变分离模式;而对于高性能,业务简单的基础数据服务,恒变分离模式应该是设计之初的一个重要原则。

    数据局部性模式(Locality Pattern)

    原理和动机

    数据局部性模式是多次请求杠杆反模式的针对性解决方案。在大数据和强调个性化服务的时代,一个服务消费几十种不同类型数据的现象非常常见,同时每一种类型的数据服务都有可能需要一个大的集群(多台机器)提供服务。这就意味着客户端的一次请求有可能会导致服务端成千上万次调用操作,很容易使系统进入多次请求杠杆反模式。在具体开发过程中,导致数据服务数量暴增的主要原因有

    首页 上一页 1 2 3 4 5 6 7 下一页 尾页 4/7/7
    】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
    上一篇Unity 游戏框架搭建 2018 (一) 架.. 下一篇SSM衍生的配置文件

    最新文章

    热门文章

    Hot 文章

    Python

    C 语言

    C++基础

    大数据基础

    linux编程基础

    C/C++面试题目