《从零开始学习架构》读书笔记之存储高性能
在前面之前文章中,简单的阐述了什么是架构、架构的目的是什么、设计架构的原则、以及设计架构的流程。接下来几篇文章将具体从高性能、高可用和可扩展三个角度分析架构模式。
首先可以将影响架构的高性能的因素分为两方面:一是存储高性能,另一个是计算高性能。这篇文章主要介绍为了满足高性能,如何去提升系统的存储能力。
关系数据库
虽然技术在不断发展,但是关系数据库依旧是很多业务系统中的关键和核心存储系统。为了应对随着业务发展的海量数据,关系数据库除了可以从原来的单机数据库优化升级成数据库集群,还可以通过读写分离,以及分库分表的方式,来缓解访问和存储的压力。
1.读写分离
其原理是将数据库读写操作分散到不同的节点上,从而将访问压力分散到集群中多个数据库服务节点上。基本实现如下:a.数据库服务器搭建主从集群;b.数据库主机负责读写操作,从机只负责读操作;c.数据库主机通过复制将数据同步到从机,每台数据库服务器都存储了所有的业务数据;d.业务服务器将写操作发给数据库主机,将读操作发给数据库从机。
但由于主从复制过程中有延迟现象,可能会导致业务上处理有问题。解决这个问题的常见方法有:a.写操作后的读操作指定发给数据库主服务器;b.读从机失败后再读一次主机;c.关键业务读写操作全部指向主机,非关键业务采用读写分离;
2.分库分表
虽然读写分离解决了数据库的访问压力,但是没有解决数据库的存储压力,从而出现了分库分表设计方案。分库分表其实包括两个方法:分库和分表。
分库,也可以理解为业务分库,即按照业务模块将数据库分散到不同的数据库服务器。虽然分库能够分散数据的存储和访问压力,但是也带来了新问题:join操作问题、事务问题、成本问题。这些问题从不同程度上,增加了系统的复杂度和成本。
分表,通常有两种方式:垂直分表和水平分表。垂直分表适合将表中某些不常用且占了大量空间的列拆分出去。水平分表则适合表行数特别大的表,如何判断,具体还要看表的访问性能。
相比垂直分表,水平分表会引入更多的复杂性,主要是路由、join操作、count()操作、order by操作。
3.方案的实现
读写分离需要将读写操作区分开来,然后访问不同的数据库服务器。分库分表需要根据不同的数据访问不同的数据库服务器,两者本质都是一种分配机制,也就是将不同的sql语句发送到不同的数据库服务器。
常见的分配实现方式有两种:程序代码封装和中间件代码封装。
程序代码封装就是在代码中抽象一个数据访问层来实现读写分离、分库。而中间件封装是指独立一套系统出来,实现读写分离和分库分表操作。
非关系性数据库-NoSQL
由于关系型数据库的缺点:a.行记录,无法存储数据结构;b.schema扩展不方便;c.在大数据场景下I/O较高;d.全文搜素功能比较弱。所以,分别诞生了不同的NoSQL解决方案。常见的方案有:K-V存储、文档数据库、列式数据库、全文搜索引擎。
K-V存储,可以解决关系数据库无法存储数据结构的问题。Redis是K-V存储的典型代表,它的主要缺点是不支持完整的ACID事务,也就是它只能保证隔离性和一致性,无法保证原子性和持久性。
文档数据库,可以解决关系数据库强schema约束的问题。它可以存储和读取任意的数据,其具有新增字段简单、历史数据不会出错、可以很容易存储复杂的数据等优点。但它也有缺点:不支持事务、以及无法实现关系数据库的join操作。
列式数据库,即按照列来存储数据的数据库,可以解决关系数据库大数据场景下的I/O问题。一般将列式存储应用在离线的大数据分析和统计场景中,因为这种场景主要是针对部分列进行操作,且数据写入后就无须再更新删除。
全文搜索引擎,可以解决关系数据库的全文搜索性能问题。其基本原理是使用“倒排索引”,也就是建立单词到文档的索引。从而实现根据关键词来查询文档内容。
缓存
缓存的出现是为了弥补存储系统在读多写少等场景下的不足。其基本原理是将可能重复使用的数据放到内存中,一次生成,多次使用,避免每次使用都去访问存储系统。
当然在使用缓存时,需要考虑三种场景问题:缓存穿透、缓存雪崩、缓存热点。
缓存穿透,是指缓存没有发挥作用,常见情况有两种:存储数据不存在、生成缓存数据需要耗费大量时间或资源。可以通过设置默认值解决前一种情况,而对于第二种情况,作者的建议是识别爬虫,并禁止访问或者是做好监控,发现问题及时处理。
缓存雪崩是指当前缓存失效(过期)后引发系统性能急剧下降的情况。常见的处理方式有:更新锁机制和后台更新机制。更新锁机制就是指,对缓存更新操作进行加锁保护,保证只有一个线程能够进行缓存更新,未能获得更新锁的线程要么等待锁释放,要么返回默认值。后台更新机制又可以分为定时读取和消息队列通知。
缓存热点指大部分甚至所有业务请求都命中同一份缓存数据。解决方案就是,复制多份缓存,将请求分散到多个缓存服务器上,减轻缓存热点导致的单台缓存服务器压力。