1.1 海量数据存储问题及解决方案
如今随着互联网的发展,数据的量级也是成指数的增长,从GB到TB到PB。对数
据的各种操作也是愈加的困难,传统单体的关系性数据库已经无法满足快速查
询与插入数据的需求。
阿里数据中心内景( 阿里、百度、腾讯这样的互联网巨头,数据量据说已经接近
EB级)
遇到的问题
1.用户请求量大
2.单库的数据量过大
3.单表的数据量过大
解决方案
单机数据库 --> 主从架构 ---> 分库分表
1.2 项目架构的演进
1.2.1 理财平台 - V1.0
此时项目是一个单体应用架构 (一个归档包(可以是JAR、WAR、EAR或其它归
档格式)包含所有功能的应用程序,通常称为单体应用)
这个阶段是公司发展的早期阶段,系统架构如上图所示。我们经常会在单台服
务器上运行我们所有的程序和软件。
在项目运行初期,User表、Order表、等等各种表都在同一个数据库中,每个
表都包含了大量的字段。在用户量比较少,访问量也比较少的时候,单库单表
不存在问题。
这个阶段一般是属于业务规模不是很大的公司使用,因为机器都是单台的话,
随着我们业务规模的增长,慢慢的我们的网站就会出现一些瓶颈和隐患问题
1.2.2 理财平台 - V1.x
随着访问量的继续不断增加,单台应用服务器已经无法满足我们的需求。所以
我们通过增 加应用服务器的方式来将服务器集群化。
存在的问题
采用了应用服务器高可用集群的架构之后,应用层的性能被我们拉上来了,但是数
据库的负载也在增加,随着访问量的提高,所有的压力都将集中在数据库这一层.
1.2.3 理财平台-V2.0 版本
如何去提高数据库层面的性能呢?
数据库主从复制、读写分离
写10000 -> 3分钟, 读10000->5秒, 读操作占整体操作8成,写操作2成。
读写分离的数据节点中的数据内容是一致。
使用主从复制+读写分离一定程度上可以解决问题,但是随着用户量的增加、访
问量的增加、数据量的增加依然会带来大量的问题.
1.2.4 理财平台-V2.x 版本
随着访问量的持续不断增加,慢慢的我们的系统项目会出现许多用户访问同一
内容的情况,比如秒杀活动,抢购活动等。
那么对于这些热点数据的访问,没必要每次都从数据库重读取,这时我们可以
使用到缓存技术,比如 redis、memcache 来作为我们应用层的缓存。
数据库主从复制、读写分离 +缓存技术
存在的问题
1.缓存只能缓解读取压力,数据库的写入压力还是很大
2.且随着数据量的继续增大,性能还是很缓慢
随着数据库的压力持续增加,数据库的瓶颈仍然是个最大的问题。因此我们可以考虑对数据的垂直拆分和水平拆分。
1.3 分库分表
1.3.1 什么是分库分表
简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。
1.3.2 分库分表的方式
分库分表包括: 垂直分库、垂直分表、水平分库、水平分表 四种方式。
1.3.2.1 垂直分库
数据库中不同的表对应着不同的业务,垂直切分是指按照业务的不同将表进行分类,分布到不同的数据库上面。
将数据库部署在不同服务器上,从而达到多个服务器共同分摊压力的效果。
1.3.2.2 垂直分表
表中字段太多且包含大字段的时候,在查询时对数据库的IO、内存会受到影响,同时更新数据时,产生的binlog文件会很大,MySQL在主从同步时也会有延迟的风险。
1.将一个表按照字段分成多表,每个表存储其中一部分字段。
垂直拆分带来的一些提升
1.解决业务层面的耦合,业务清晰
2.能对不同业务的数据进行分级管理、维护、监控、扩展等
3.高并发场景下,垂直分库一定程度的提高访问性能
1.3.2.3 水平分库
将单张表的数据切分到多个服务器上去,每个服务器具有相应的库与表,只是表中数据集合不同。 水平分库分表能够有效的缓解单机和单库的性能瓶颈和压力,突破IO、连接数、硬件资源等的瓶颈.
简单讲就是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面, 例如将订单表 按照id是奇数还是偶数, 分别存储在不同的库中。
1.3.2.4 水平分表
针对数据量巨大的单张表(比如订单表),按照规则把一张表的数据切分到多张表里面去。 但是这些表还是在同一个库中,所以库级别的数据库操作还是有IO瓶颈。
总结
垂直分表: 将一个表按照字段分成多表,每个表存储其中一部分字段。
垂直分库: 根据表的业务不同,分别存放在不同的库中,这些库分别部署在不同的服务器.
水平分库: 把一张表的数据按照一定规则,分配到不同的数据库,每一个库只有这张表的部分数据.
水平分表: 把一张表的数据按照一定规则,分配到同一个数据库的多张表中,每个表只有这个表的部分数据.
1.4 分库分表的规则
水平分库规则
1.不跨库、不跨表,保证同一类的数据都在同一个服务器上面。
2.数据在切分之前,需要考虑如何高效的进行数据获取,如果每次查询都要跨越多个节点,就需要谨慎使用。
水平分表规则
1. RANGE划分
时间:按照年、月、日去切分。
地域:按照省或市去切分。
大小:从0到1000000一个表。
2. HASH
用户ID取模
1.5 分库分表带来的问题及解决方案
1.5.1 事务一致性问题
当我们需要更新的内容同时分布在不同的库时, 不可避免的会产生跨库的事务问题. 原来在一个数据库操作, 本地事务就可以进行控制, 分库之后 一个请求可能要访问多个数据库,如何保证事务的一致性,目前还没有简单的解决方案.
1.5.2 跨节点关联的问题
在分库之后, 原来在一个库中的一些表,被分散到多个库,并且这些数据库可能还不在一台服务器,无法关联查询.解决这种关联查询,需要我们在代码层面进行控制,将关联查询拆开执行,然后再将获取到的结果进行拼装.
1.5.3 分页排序查询的问题
分库并行查询时,如果用到了分页 每个库返回的结果集本身是无序的, 只有将多个库中的数据先查出来,然后再根据排序字段在内存中进行排序,如果查询结果过大也是十分消耗资源的.
1.5.4 主键避重问题
在分库分表的环境中,表中的数据存储在不同的数据库, 主键自增无法保证ID不重复, 需要单独设计全局主键.
1.5.5 公共表的问题
不同的数据库,都需要从公共表中获取数据. 某一个数据库更新看公共表其他数据库的公共表数据需要进行同步.