关于存储,无不例外要和数据库打交道,目前比较主流的一些关系型数据库,非关系型数据库是作为架构师必须要了解的东西。但要做到高性能,其中还是有很多学问的。
我们先来谈一谈关系型数据库,因为其可靠性,强大的ACID特性,以及完备的集群方案,任然是核心业务的主流存储方案。那么如何在关系型数据库下做高可用存储方案,目前主流的还是采用集群方案进行数据扩展比如读写分离方案,分库分表
我们假设系统随着用户的增多,那么单节点数据库肯定会成为性能瓶顶,那么对于我们来说成本最低的解决方案就是读写分离,因为大多数的业务都是读多写少,采用数据库的主从功能很容易就实现这一点,代码层面只需要做数据源的适配就可以。此时我们的架构是这样子的:
这样做明显会带来一个问题,就是数据复制之间出现的延迟问题,把核心的和不能容忍延迟的读取操作全部放到写服务器去读。这样做等业务有一定的规模时数据的存储和查询效率依然会成为瓶颈,那么这时候我们就需要考虑分库分表了,分库分表的成本是比较高的,因为分库后我们就不得不面对集群的事务问题,数据库join的问题和成本问题。此时我们的架构图是这样子的:
将不同的业务数据分散存储到不同的数据库服务器,能够支撑百万甚至千万用户的规模,但如果业务继续发展,同一业务的单表数据此时会成为我们的性能瓶顶,此时我们所要做的就是拆分数据表,常用的有水平拆分和垂直拆分,垂直拆分比较简单,所带来的问题就是原本一次就可以查询出的东西现在需要查询多次才可以,我们可以根据信息的活跃度将不常用的数据表拆分出来。如果单表数据过多的情况下就必须要水平拆分表了,现在我们需要解决的问题就是我们的数据到底存储在那张表里,此时就得引入路由算法常见的有范围路由,Hash路由,配置路由。水平分表后让数据库的group,order,join操作变得更加复杂。生产中还是要靠中间件去解耦我们的业务。目前mycat算是一个比较完善的中间件,基本开箱即用。
下来要说的就是nosql这块,从它的定义来看,not only sql,它的出现并不是为了去替代传统的关系型数据库,而是对关系型数据库的一个有力补充。常见的nosql方案有如下四类:
1.K-V存储:解决关系型数据库无法存储数据结构的问题,以redis为代表
2.文档数据库:解决关系数据库强schema约束的问题,以mongoDB为代表
3.列式数据库:解决关系数据库大数据场景下的IO问题,以Habse为代表
4.全文搜索引擎:解决关系数据库的全文搜索性能问题,以Elasticsearch为代表
目前来看Nosql数据库根据场景只是实现了关系数据库ACID的某些部分对事务的支持不是很理想,但也不能因此而忽略了它带给我们好的一面。比如速度,比如表结构的扩展(mongoDB存储基于BSON格式的,很容易去扩展原有的字段,而不会影响到历史数据),列式数据库常用于大数据场景中,因为其出色的存储压缩比和较小的IO消耗而闻名,通常用于静态数据处理和离线计算这块。因为数据被频繁的更新,列式数据库的优势可能就会变为劣势,因为频繁的解压数据让数据处理效率方面大打折扣。
最后谈谈缓存,缓存通常被用于读多写少的系统中,关于缓存有以下几个基本的概念需要我们理解。
1.缓存穿透:缓存穿透是指缓存没有发挥作用,造成缓存穿透有以下两个因素一是本身数据不存在造成的,二是生成缓存数据需要一定的时间,我们需要根据我们自己的业务去完善我们的设计
2.缓存雪崩:缓存大面积失效,这样大量的请求将直接访问我们数据库造成系统崩溃。缓存雪崩常见的解决方案有两种:更新锁机制(对于更新缓存的操作进行加锁保护,保证只有一个线程能够进行缓存更新)和后台跟新机制(由后台更新缓存而不是业务线程,可以采用定时读取,消息队列通知的方式)
3:缓存热点:对于访问比较高热点缓存进行缓存复制,以减少单个缓存服务器的压力。