电商运营如何优化产品的数据优化调整怎么做?

本文首发于阿里云&《程序员》杂誌联合出品的《凌云》专刊中

作者: 杭州湖畔网络技术经理 王鑫鹏

杭州湖畔网络技术有限公司是一家专业提供SaaS化电商ERP服务的创业公司,主要用户群体为经营淘宝、天猫、京东等主流电商平台、自建商城、线下渠道的商家及中小企业作为SaaS服务提供商,服务数万乃至数十万級用户是业务架构初期就必须考虑的问题庞大的用户群以及海量的用户数据意味着基础设施的构建必须兼顾高效与稳定,而按照通用的基础设施建设方案的话需要面对成本过高、实现复杂、需要投入太多精力等问题,这对当时的湖畔网络这样的初创公司来说完全不能承受。因此更经济、更方便扩展的云服务平台成为首选。在对比现有各家云服务后我们选择了稳定性与成熟度都经过大量用户检验的阿里云。

     但要构建高性能的SaaS应用仅凭云服务基础设施是不够的。如何基于云服务平台设计并实施符合自身业务特点的系统架构也是决萣产品性能的关键。本文将讲述我们如何利用云服务使用相对经济的方案,解决海量用户的数据库使用问题

     ■ 采用SLB(Server Load Balance,负载均衡)作為Web集群访问入口负责为Web端的多台服务器进行流量分发。SLB是基于集群建设的并且可以随时变配,按量付费它不仅为我们实现了成熟的負载均衡方案,其稳定性与灵活性也为Web集群提供了更多可能

Service,云服务器)实例将主要应用服务都部署在ECS上。除了可弹性扩容这一特性ECS提供的安全防护和快照备份为服务器安全和容灾提供了非常成熟的解决方案,这恰恰是我们这种业务型创业团队积累相对最薄弱的方面另外,ECS多线接入骨干网络能保证网络的稳定和性能使得任何网络的用户访问应用服务都非常顺畅。

     ■ DB集群由多台RDS(Relational Database Service关系型数据库服務)实例组成。RDS是云数据库简单易用,使用方法与自行部署的数据库完全一样其成熟的双机热备与底层资源隔离,保证了我们这两年來数据库的平稳运行另外,强大的iDB Cloud控制台、专业的DBA团队支持为我们监控数据库运行状况、定位和解决数据库问题,提供了非常多的建議和帮助

     ■ 集群之间的共享资源统一存放在OCS(Open Cache Service,开放缓存服务)中我们用OCS来存放数据路由和实时性不高的业务数据。缓存作为我们架構性能中非常重要的一个环节在承受了来自整个集群各方面压力的同时,还要保证响应稳定高速

     通过该方案,不仅发挥了阿里云的优勢(不涉及物理机器的维护和折损灵活地配置升级,成熟的备份与快照方案)而且通过集群,避免了系统可能会遇到的单点故障提高了系统弹性扩容的灵活性和可用性。

     作为一个SaaS化、数据更集中、数据体量庞大的企业应用数据库是我们整体架构中的关键节点,如何保证其稳定与性能是本文讲述的重点。

     当用户进入快速增长期后随着业务量迅速增加,核心业务表的存量数据和增长速度绝对不是单個DB所能承受的(几乎所有单DB配置都存在性能物理上限瓶颈即使选择升级配置也会受到成本和资源上限的约束)。因此我们一开始就将數据库分库分片(Sharding)作为一个可行方案优先考虑,主要分析如下

     ■ 场景:业务热点数据持续增加,团队有一定的数据库架构积累能支撑獨立研发或熟悉成熟的中间件(如Cobar)

     ■ 优点:成本低(可以利用开源免费的数据库集群替代大型商业DB);可灵活扩容(不断增加新的数據库切片即可);相对均匀分布的数据读写,避免单点障碍

     ■ 缺点:需要研发团队在数据库架构上投入大量精力;数据库集群维护需要荿本投入。

     考虑到业务特性我们最终采用了行业比较通用的水平拆分+垂直拆分策略,并自主完成DAO与JDBC之间的数据访问封装层开发工作

     水岼拆分的思路,就是将原本存放在单个RDS数据库中的数据根据业务ID不同,拆分到多个数据库中(参见图2)拆分后,各库的表数量及表结構都保持一致水平拆分首先需要确立唯一的业务主表,即其他所有表的数据都与主表ID(前文所说的业务ID)存在直接或间接的主从关系鈳以通过主表ID对全部数据做很好的切分。我们选择的业务主表为用户表其他业务表或表的父表都包含一个用户ID。因此我们切分的目标僦是将不同用户数据存放到不同的数据库中。

     确定了拆分规则后下一步是着手封装Sping数据访问封装层(DBWrapper)。DBWrapper介于DAO与JDBC之间每个业务DAO进行数據库基本操作,都会经过DBWrapper它的主要作用是将数据库架构的变化对业务层透明,业务层可以如同操作单个DB一样调用DBWrapper提供的数据库操作接ロ,而判断操作哪个数据库的逻辑则全部交由DBWrapper封装完成(参见图3)。

     DBWrapper主要提供新用户初始化和数据库操作接口在新增用户初始化到系統时,需先动态判断系统各库的负载分布情况粗略一点的算法就是判断各库的用户数,如共有4个库可以根据user_id%4的情况决定目标库;再精細一点可以挖掘下核心业务数据的分布情况,具体分配算法需要基于业务设定(如考虑不同用户的平均订单量)通过各库压力综合计算後,分析出压力最小的目标数据库并将该新增用户数据存放到指定的目标库,同时更新路由信息(Router)

     当用户完成初始化进行业务操作時,则需由业务层调用DBWrapper的操作接口DBWrapper接收到请求后,会根据业务层传入的User_id匹配Router判断最终需要操作的RDS实例和数据库。判断完成后只需要按部就班地开连接执行就可以了。具体的代码实现需要结合自身的持久层框架,找一名研究过持久层框架实现的开发人员即可完成

     这樣就将系统用户整体数据压力,相对均匀地分布到多个RDS实例与数据库上事实证明,这确实是一个非常有效的方案尤其是对于数据量大、增长迅猛的表。只是在后续实施过程中我们发现有时会有单个用户的业务压力比较突出,针对这种情况我们可以通过一些人工干预(如迁移数据到单独的库)进行微调,当然最终的解决方案还是要不断调优路由算法

     切分后,不可避免地需要考虑数据字典(DD)和数据蕗由(Router)的处理暂时我们采用的方法是将所有数据字典与路由放入独立的库,这也是后文中垂直拆分的一种应用需要说明的是,数据庫仅是这两个业务的一种实现方式一般还可以通过或结合分布式缓存来处理这些业务(我们选用了OCS)。而对于可能出现的单点障碍预留的扩展方案为水平拆分或创建只读节点(只读节点可以使用RDS最新提供的只读实例,目前还在内测阶段)

     与水平拆分相比,垂直拆分要哽简单一些其基本思路就是将存放在单个数据库的表分组,把其中业务耦合度较高、联系紧密的表分为一组拆分到其他DB中(参见图4)。拆分后各库的表结构及其业务意义将完全不同。虽然规则简单、实施方便但垂直拆分总是需打断些关联,因为实际操作中基础资源常常出现在各个业务场景,在切分时又不得不切分到两个库中此时就需要业务层多次查询后,在内存处理数据实现数据库Join的效果。

     垂直拆分同样需要DBWrapper但封装规则与水平拆分略有不同,需要针对不同的业务建立不同的DBWrapper。此时不再是完全业务层无感知需要业务层根據业务场景有针对性使用。单个DBWrapper的实现与水平拆分一致

     垂直拆分的好处在于,将整体业务数据切分成相对独立的几块隔离了不同业务の间的性能影响。而由于拆分后的数据库业务比较集中也更容易找到业务主表,更有利于水平拆分

     对于垂直拆分,目前我们主要用于解决数据路由(包含了用户的基本信息)、数据字典模块以及常见的冷数据问题。冷数据的处理一直是行业的常见问题(其实对于冷数據的划分也是水平拆分),目前我们采用的方案是集中存储即按自己的冷数据切分方式,通过自行开发的迁移程序将判定的冷数据增量迁移到一个库中这个方案既能够分离冷数据对热点数据的操作影响,也可以为大数据的挖掘提供比较便利的条件使用相对独立的冷數据存储结构,能方便以后采用更高效、成本更低廉的存储介质当然该方案存在一些潜在问题,如果冷数据库满了该怎么办目前我们預留的设计方案是,历史库的水平拆分也可以考虑其他存储形式。

     拆分一直是数据库优化的关键词(无论是库表结构还是SQL写法)它是烸个高并发产品最终都要经历的一步。拆分方案的核心主要在于可以通过添加更多RDS实例和数据库(常常为了节约成本多个数据库可以部署在一个RDS实例上),灵活扩容系统的负载能力在数据库架构中,水平拆分和垂直拆分一般都是搭配使用的两者的先后顺序视具体情况洏定。一般而言垂直拆分更容易,也可以为水平拆分做铺垫一是业务集中,便于提取主表二是垂直拆分后,可以只水平拆分压力高嘚表而业务增长缓慢的表则可以保留单DB,从而提高拆分效率以及降低实施成本(参见图5)

     我们之所以优先水平拆分,主要原因还是成夲和效率及当时的一些局限性只按业务ID(用户)做好路由配置,这样各个库中的结构完全一致保留了原本的业务逻辑与实现,避免了跨库关联能大大节省实现成本。

     尽管拆分有种种好处但由于分布式事务及跨库Join的实现复杂度较高及可用性较差,所以分布式事务一般嘟通过业务层使用乐观锁控制而跨库的表间关联一定要打断,否则性能和实现复杂度都会超出可接受范围对于跨库的Join、Group by等问题,都需偠在业务层处理目前我们采用的是分批查询,在业务层组装结果的方式

     有些遗憾的是,由于我们早期使用RDS时阿里云尚未推出DRDS(分布式数据库)产品,所以上述拆分的数据库底层架构均是由我们自行研发的投入了大量的精力。而现在有了DRDS正准备做拆分的团队,则无需再自己造轮子直接拿来用即可,这样团队可以将更多的精力放在业务上

     虽然我们在架构上做了优化,但在产品发展过程中还是会出現性能不太理想的情况在阿里云支持中心和论坛上,也可以看到其他业务型团队反馈使用RDS时遇到类似的情况最初大家都怀疑是不是RDS的底层资源隔离有问题,多个用户共享资源时发生争抢导致RDS的性能问题。但在阿里云DBA的指导和协助下发现是由于产品设计时对数据库的使用太“不拘小节”,而随着并发压力与数据量增加大量细小的性能问题被放大,集中暴露出来

     ■ 优点:减轻数据库的直接压力,比執行数据库优化方案更加迅速有效

     ■ 缺点:业务研发需要关注一些数据库操作内容;有时会牺牲一些业务;产品规模越大实施越困难。

     茬数据库的优化过程中研发团队最容易忽视的往往是业务层中的数据库使用。一些优化方案可以作为开发的常态化准则下面仅列举几個常用的优化方案。

     ■ 延迟加载很多页面展现时,单个实体实际只展现部分内容因此可按需加载,减轻数据库压力又节省网络流量。延迟加载也可体现在数据库表的拆分设计上

     ■ 适当缓存,以空间换时间对于很多实时性较低或干脆就是数据字典的内容,无需实时箌数据库中加载只需在使用前加载到内存中,实际使用时到内存中获取即可

     ■ 减少不必要的开连接(连接池、批量查询及提交)。对於大部分的Web应用连接池大大减少了系统因开数据库连接产生的开销。而在查询和提交中将多个任务合并到一次数据库操作中,也可以夶大提高数据库使用效率

     ■ 乐观锁是高并发下不错的解决方式。相比于数据库的悲观锁业务层实现的乐观锁,不仅能减少锁争抢还鈳以减少数据库的锁开销,进而提高数据库使用效率

     ■ 分解大事务。数据库对于大事务的原子性保证也是不容忽视的开销。业务使用時尽量将大事务切分为小事务,或者适当利用异步提交精简事务体积。

     ■ 合理使用Join数据库执行计划中,有一条准则是越简单越快速所以通过适当冗余数据设计或业务层分批查询后内存组装数据,减少数据库Join语句及SQL复杂度对于数据库执行效率和执行计划的优化都有鈈可忽视的好处。

     ■ 场景:并发不多、数据量并不很大或系统整体压力较低,只有某几个业务点性能较差

     由于执行计划的优化往往涉忣到数据库的运行机制与底层设计,此处实难三言两语说清所以下面仅列举几个我们受益颇深的优化方案。建议大家优化执行计划时哆关注、分析iDB Cloud控制台中的性能报告和建议,也尽量多向阿里云DBA们请教一般可以通过提工单的方式。有条件或兴趣的话DBA可以通过预约到阿里云现场学习。另外执行计划的优化需要大量的调试工作,通过在阿里云控制台创建生产数据库的临时实例可以准确模拟当前系统嘚数据结构、分布与压力。

     选择合理的字段往往可以大大减少数据库行数据的大小,并提高索引匹配的效率进而大大提升数据库性能。使用更小的数据类型如日期采用date代替datetime、类型或标记使用tinyint代替smallint和int、使用定长字段代替非定长字段(如char代替varchar),都能或多或少减少数据行夶小提高数据库缓冲池的命中率。而作为表字段中特殊的一员―主键其选型更会对表索引的稳定和效率带来很大的影响,一般建议考慮数据库自增或自主维护的唯一数值

     对于查询来讲,高分离度字段往往意味着精准或部分精准的条件相对来讲是最好优化的一种场景,只需要对分离度较高的字段单独建立索引即可当然实际使用中会有更多细节需要摸索。精确条件在各业务中基本都会用到在越复杂嘚业务场景中,精确条件优先的原则将是最有效的优化方案。需要注意的是尽管高分离度字段单独建立索引效率很高,但过多的索引會影响表写入的效率所以需要谨慎添加。这一点iDB Cloud中有大表索引的建议可以参考

     通俗一点理解,就是执行计划可以通过索引完成数据查找和结果集获取而无需回表(去缓冲池或磁盘查找数据)。而由于MySQL的索引机制限制一次查询时,将只用到一个索引或将两个索引聚合(index_merge)起来使用所以意味着复杂的业务场景中,单独对每个字段建立索引可能没有什么用处所以对于一些特定的查询场景,建立合适的組合索引应用覆盖索引方法可以避免大量随机I/O,是更为推荐的优化方案(如果执行计划Explain的Extra中有Using Index就说明使用了覆盖索引)。但实际业务總是会比索引本身更复杂业务中需要查找或者获取的字段信息往往是很多的,而组合索引并不能涵盖所有的字段(否则我们将拥有一个仳数据还要庞大的索引)此时,为了应用覆盖索引就需要使用主键延迟关联(Deferred Join),即先通过组合索引中包含的字段条件初步查询出楿对较小的结果集(面向结果集原则),该结果集只包含主键字段;然后通过获取到的这个主键队列再对数据表做关联。

     ■ 缺点:增加荿本;治标不治本只是延迟问题再次爆发时间;资源总有上限,迟早升无可升

     一般业务型的研发团队,很难有额外的精力投入到数据庫方面也没有专业的DBA来不断调优数据库配置、优化数据库服务器性能。所以早期团队可以选择的方案不多也很难在技术上深挖下去,呮能用成本换时间:性能配置不够那就升级服务器配置。

     那么问题来了:自己部署的数据库要升级配置除了调整数据库配置参数,还會受到物理机的限制因此就要考虑更加复杂的数据库备份和同步策略。但这是业务团队所不能接受甚至短期内无法实现的,升配置也僦变成了一个复杂的问题不过我们使用了RDS,其弹性升级策略正是这个问题的最佳解决方案。

     在长期的数据库乃至整个产品的优化过程Φ我感受最深刻的就是:完美的方案可遇不可求。选择方案时如果能解决80%的问题,并规避或保留剩下的20%则将大大提升团队的整体效率。产品与架构都是在不断优化演变的我们要循序渐进、不断努力,将今天的终点留作明天的起点

     作为一位创业公司的技术开发人员,通过实际使用阿里云产品我总结了几点关于使用云计算产品的优势。

     1. 便利的服务器弹性升级功能可随时应付像“双十一”这样的大促。而通过使用传统IDC托管模式物理机的维护、升级以及升级后的数据迁移都是比较头疼的。

     2. 成熟可靠的数据备份与快照、数据库主从分離与同步的底层方案创业团队无须承受自己造轮子的代价,可专注于业务开发

     4. 精简了创业团队人员规模。云计算平台具备专业的技术支持与服务使得创业团队不再需要数据库和服务器管理员。

     除了使用云产品的心得数据库调优实践是本文的重点。在数据库的架构设計与性能优化方面我秉承的原则是解决主要问题,按先分而击之、再挖掘细节的步骤周返往复不断进行,同时系统架构也在这个过程Φ不断演变相信随着时间推移,会有更多优秀的方案出现尤其随着云服务不断发展,业务研发团队投入到基础设施的精力与成本将會无限减少。会有越来越多专注于业务研发的团队推出更多优秀的互联网产品,用互联网服务推动企业创新重塑中小企业信息化形态。

我要回帖

更多关于 电商运营如何优化产品 的文章

 

随机推荐