在现代的软件系统中,几乎所有的系统都使用到了数据库,不论是关系型数据,例如MySql、SQLite、Oracle、SQLServer等,还是非关系性数据,例如mongoDB、redis等。本文已web系统为例来阐述为什么要降低数据库的压力,在提出具体方案之前先大致讲解一下现在web系统的架构,要了解web系统的架构和演变过程具体可以参考大型网站架构演变和知识体系这片文章。

现代web系统的架构

现在的大型web系统多采用分布式的架构,分布式系统面临的最大挑战就是如何在复杂的、并发的情况下保证数据的一致性问题。通常为了避免由于保证数据一致性问题而带来的困难,通常情况下都是采用多个实例,单个数据源的架构模式,简化模式如图。 
 
在这个架构中,通过不断的增加实例(webserver)可以降低应用服务器的压力,所以只要保证应用代码的质量、应用之间的低耦合性、可扩展性和可维护性等,应用服务器的压力就不再会成为整体架构中性能瓶颈,但是随着业务量的不断增加增长,或者时间的积累,沉淀下来的数据变得越来越来多,随着而来的数据库的压力变得越来越大,慢慢的性能的瓶颈主要集中在数据库上。


降低数据库压力的方法

1.合理增加索引

表索引可以加快对表中数据的检索速度,但是会降低表中数据的更新速度,所以增加表的索引一定控制在合理范围内,过多的索引不但不会降低数据库的压力,反而可能增大数据库的压力,表索引的建立一般要从具体业务场景出发,对于读多写少的场景,可以通过适当的增加索引来提高效率,对表的那些列建立索引?建立单独索引还是建立复合索引?要根据具体的业务场景来决定,建立索引之后可以针对索引对业务逻辑中使用的SQL进行优化,建立索引是最基础的手段,这里不错过多的介绍。

2.数据截转

一般情况下,业务中所处理的数据的都具有一定的时间间隔,所以可以通过对业务进行梳理,将当前时间间隔之外的数据进行截转,截转到历史数据库中,通过对业务进行拆分,当需要历史数据时,可以转到历史数据库中进行查询,或者修改,通过减少当前数据库的数据量,来减轻当前业务数据的压力。数据截转一般情况下是按照时间来进行,所以在业务员数据库设计的时候就要考虑到时间这个因素。 
数据截转可以进行间隔一段时间做一次手工的数据截转,也可以启动一个定时器,每个一段时间进行一次数据截转,推荐的方式是准实时截转,及每天在业务量较小的时间,启动任务实时截转。 
数据截转需要注意的几个问题:(1)外键关联关系(特别是有主键ID的关联的)注意在截转的历史数据库中的关联关系是否正确。(2)保证生产库和历史库的业务关联关系,从而避免历史库的数据需要关联生产库中的数据。

3.增加缓存

缓存是降低数据压力一个强有力的手段,基本是所有系统大型web系统中都会使用到,所以现代的大型web系统的架构一般如图。 
 
请求1到达webserver之后,首先执行2访问缓存,如果hit则返回,miss则执行3访问数据库,在执行4同步到缓存中,再返回。但是不是缓存并不是万能的,缓存也有其使用的业务场景,一般在读多写少,数据重复查询比较集中的场景下,缓存可以大大提高性能,缓存操作顺序非常重要,不合理的操作顺序,在并发场景下常常会导致数据的不一致,缓存的具体操作可以参考缓存架构设计细节二三事这边文章。

4.生成宽表,冗余数据

有些业务例如报表、数据汇总等需要数据量较多,此时可能需要进行多表联合查询,联合查询操作非常消耗数据库的性能,所以在这种业务场景下为了避免过大的性能消耗,往往需要将查询时的多个表按照关联条件进行关联,生成一张含有冗余信息的包含所有表的多个字段的大宽表,这样在进行查询时,只在一张表中进行查询,性能明显得到提升。大宽表的生成是在业务流程中生成还是通过异步化任务来生成,根据具体的业务逻辑来定。

5.修改关系型数据库为非关系性数据库

非关系型数据库,也就是我们通常说的NoSQL数据,最常见就是key/value类型的数据库,这类数据库不强调表的关系,但是查询速度非常快,所在某些具体场景下,我们应该优先选择NoSQL数据库,例如字典信息表的查询。

6.读写分离

如果采用单点数据数据库,就算对数据进行上述的相关优化,但是由于其本身的单点性,所以随着流量的激增,数据库仍然会成为系统的瓶颈,如何对数据进行拆分来解决这个问题了,读写分离就是最常用的方法,读写分离的原理如下图。 
 
读写分离技术现在已经应用的很成熟,通过将数据拆分为两个实例,读写分离操作改善了数据单点的瓶颈,分摊了数据库压力,而且当主数据库宕机之后可以迅速的切换到从库,而不会导致业务不可用,同时也起到数据备份的作用,由于存在两个数据实例,所以数据怎么由主库同步到从库、主从之间延迟引发的数据不一致问题,以及怎么来分离业务中读和写操作成为要解决的问题成为要解决的问题。主从同步可以参考Mysql主从架构的复制原理及配置这篇文章,从主数据一致可以参考DB主从一致性的几种解决方法这篇文章。

7.数据库拆分

采用读写分离之后,数据库已经变为两份实例,数据库的压力已经得到分摊,如果数据库的压力还是过大时,这是就要从业务方面着手,将具体业务细分,将业务对应的表分拆到不同的数据库当中,如下图。 

业务变动较大,同时要对系统内部之间的相互调用提供接口,调用方式可以选用RPC、Restful、JMQ消息等方式。一般情况下,数据库垂直拆分做的足够细分的话,加上读写分离技术,加上适当的数据截转就可以满足一般的大型业务系统对性能的需求。

8.表的垂直拆分

数据库可以进行垂直拆分,当然也可以对数据库中的表进行垂直拆分,对表进行拆分就是对数据拆分的再拆分,如图。种解决方法只适用于一些特定的场景,例如对表进行垂直拆分,通过异步化调用将所有任务异步化,前提是总的任务可以进行分布的异步化操作,在实际应用比较少,因为设计的表只要复合三范式的要求,一般是很难在进行拆分的,应用较多是对表进行水平拆分。 

9.表的水平拆分

如果已经做了数据库拆分,并且进行了读写分离,数据压力还是过大,主要原因就是数据库表中的记录太多,或者对数据进行了截转,但是对历史数据的操作还是比较频繁的,且随着截转的历史数据越来越多,历史数据库的压力也边的也变的越来越大,这时有两种解决方案:第一种方案就是对数据库中的表进行垂直拆分,从而不用在截转数据,通过不断对表进行水平拆分,保证数据数据库中单表的记录数保持在一个高性能合理的范围之类,通过扩容将不同分配到不同的数据中(分库分表)来保证数据库的压力,应用在访问时,通过分库分表的条件进行路由,就可以取到数据。第二种就是仍旧对数据进行截转,当历史数据信息过多从而导致数据库压力过大时,采用搜索引擎的方式来解决。相比于第一种操作第二种方案适用于读操作上,对与写操作,具有一定的局限性,第一种方案具有一定的通用性。对表进行水平拆分的过程如图所示。 
 
在进行进行具体水平拆分之前,我们需要考虑这样几个问题

  1. 制定什么样的路由规则
  2. 如何尽量避免跨库或者跨表操作
  3. 如何尽可能的避免全库全表扫描
  4. 如何保证每个库的负载处于基本尽可能均衡的状态
  5. 如何实时跨库访问事物
  6. 如何实时聚合操作
  7. 如何保证扩容的方便性

1. 制定什么样的路由规则

2. 如何尽量避免跨库或者跨表操作

3. 如何尽可能的避免全库全表扫描

4. 如何保证每个库的负载处于基本尽可能均衡的状态

5. 如何实时跨库访问事物

6. 如何实时聚合操作

7. 如何保证扩容的方便性

web架构延变的更多相关文章

  1. 可扩展Web架构与分布式系统(转)

    1.1. web分布式系统的设计原则 搭建和运营一个可伸缩的web站点或者应用程序意味着什么?在原始层面上这仅仅是用户通过互联网连接到远程资源-使系统变得可伸缩的部分是将资源.或者访问的资源,分布于多 ...

  2. Web 架构师的能力(转)

    文/刘如鸿 最近和几个朋友在谈到时下流行的Web 2.0,也提到了其中最重要的角色——架构师.多方各有争执,不外乎是因为背景和视角的缘故,包括架构一词,本身就从建筑学借鉴而来,至于架构师,则可以 简单 ...

  3. 可扩展Web架构与分布式系统

    原文:可扩展Web架构与分布式系统 开放源代码已经成为一些大型网站的基本原则.而在这些网站成长的过程中,一些优秀的实践经验和规则也出现在他们的结构中.本文旨在介绍一些在大型网站结构设计的过程中需要注意 ...

  4. 可伸缩Web架构与分布式系统(1)

    开源软件近年来已变为构建一些大型网站的基础组件.并且伴随着网站的成长,围绕着它们架构的最佳实践和指导准则已经显露.这篇文章旨在涉及一些在设计大型网站时需要考虑的关键问题和一些为达到这些目标所使用的组件 ...

  5. 【转载】WEB架构师成长之路

    本人也是coding很多年,虽然很失败,但也总算有点失败的心得,不过我在中国,大多数程序员都是像我一样,在一直走着弯路,如果想成为一个架构师,就必须走正确的路,否则离目标越来越远,正在辛苦工作的程序员 ...

  6. 从http简介到网络分层及web架构

    浏览器发起HTTP请求的典型场景 a stateless application-level request/response protocol that uses extensible semant ...

  7. 可扩展的 Web 架构与分布式系统

    作者:Kate Matsudaira 译者:尹星 本文介绍了分布式架构是如何解决系统扩展性问题的粗略方法,适合刚刚入门分布式系统的同学,我把整篇文章翻译如下,希望给你一些启发. 备注:[idea]标注 ...

  8. WEB架构师成长系列索引

    WEB架构师成长系列索引 http://www.cnblogs.com/seesea125/archive/2012/04/17/2453256.html

  9. WEB架构师成长之路-架构师都要懂哪些知识 转

    Web架构师究竟都要学些什么?具备哪些能力呢?先网上查查架构师的大概的定义,参见架构师修炼之道这篇文章,写的还不错,再查查公司招聘Web架构师的要求. 总结起来大概有下面几点技能要求: 一. 架构师有 ...

随机推荐

  1. Android动态控制状态栏显示和隐藏

    记得之前有朋友在留言里让我写一篇关于沉浸式状态栏的文章,正巧我确实有这个打算,那么本篇就给大家带来一次沉浸式状态栏的微技巧讲解. 其实说到沉浸式状态栏这个名字我也是感到很无奈,真不知道这种叫法是谁先发 ...

  2. .net core定时任务

    1.HangFire HangFire官网 Hangfire项目实践分享 :  讲解的比较详细 2.Quartz.NET https://www.cnblogs.com/best/p/7658573. ...

  3. 树形插件 --- zTree

    地址:http://www.treejs.cn/v3/api.php

  4. Oracle 11g服务器安装详细步骤——图文教程(系统 windows server 2012 R2)

    Oracle 11g服务器安装的相关问题,下面小编就带大家一起来下载.安装. 方法/步骤 1 大家可以根据自己的操作系统是多少位(32位或64位)的,到官网下载相应的安装程序,如下图所示. 有一点需要 ...

  5. Hibernate api 之常见的类(配置类,会话工厂类,会话类)

    1:Configuration :配置管理类对象 1.1:config.configure(): 加载主配置文件的方法(hibernate.cfg.xml) ,默认加载src/hibernate.cf ...

  6. NodeMCU入门(3):断线自动重连,指示灯显示连接状态

    准备工作 1.NodeMCU模块 2.ESPlorer v0.2.0-rc6 事件监听器 NodeMCU采用了事件响应的方式.也就是说,只需为事件设置一个回调函数,当事件发生时,回调函数就会被调用. ...

  7. Pig和Hive的对比

    Pig Pig是一种编程语言,它简化了Hadoop常见的工作任务.Pig可加载数据.表达转换数据以及存储最终结果.Pig内置的操作使得半结构化数据变得有意义(如日志文件).同时Pig可扩展使用Java ...

  8. 微信小程序 --- 表单输入验证(手机号、邮箱验证、输入非空)

    js代码 Page({                   /**    * 页面的初始数据    */         data: {         indicatorDots: false,   ...

  9. Windows10下 tensorflow-gpu 配置

    引言 越来越多的的人入坑机器学习,深度学习,tensorflow 作为目前十分流行又强大的一个框架,自然会有越来越多的新人(我也刚入门)准备使用,一般装的都是 CPU 版的 tensorflow,然而 ...

  10. Ubuntu18.10&Ubuntu18.04安装Python虚拟环境

    Ubuntu18.04版本里面自带了最新的Python3.6.5版本,在安装Python虚拟环境时需注意: 1.首先是安装两个包 pip3 install virtualenv # python虚拟环 ...