前言
对于一个大型的互联网应用,每天几十亿的PV无疑对数据库造成了相当高的负载。对于系统的稳定性和扩展性造成了极大的问题。通过数据切分来提高网站性能,横向扩展数据层已经成为架构研发人员首选的方式。
数据切分:可以降低单台机器的负载,同时最大限度的降低了宕机造成的损失;
负载均衡策略:可以降低单台机器的访问负载,降低宕机的可能性;
集群方案:解决了数据库宕机带来的单点数据库不能访问的问题;
读写分离策略:最大限度了提高了应用中读取数据的速度和并发量;
这里主要谈及数据切分和其相关数据库优化(主从复制,读写分离)的概念
数据切分
其主要目的是为突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。
切分后遇到很多问题(例如:跨库join,父子表join, 分布式事务等),这也是需要考虑的。
数据库分表
垂直划分和水平划分
垂直切分---分模块使用字段不同的而划分不同字段结构的表;水平切分---分同一个模块下的多个结构相同的子表
1、垂直划分
把不同功能,不同使用频率的数据列分别放到不同的表中,但是如果同一个模块的数据量太大就会存在性能瓶颈
例如:把常用的字段放一个表,不常用的放一个表
把字段比较大的比如text的字段拆出来放一个表里面
使用的话是根据具体业务来拆,查询时使用多表联查,可以再配合redis存储
2、水平划分
垂直切分解决不了大表的瓶颈,如果同一个功能中表的数据量过大,就要对该表进行切分,为水平切分
例如:用户表user分为 user_1 , user_2分别存储男用户和女用户
数据库分库
1、垂直划分
基本的思路就是按照业务模块来划分出不同的数据库,而不是像早期一样将所有的数据表都放到同一个数据库中。
例如:商场订单模块放主机1中数据库, 商品模块放主机2中数据库
2、水平划分
水平分库方式主要根据数据属性(如商品所属地市, 种类)拆分物理数据库,从而解决单库中数据量过大IO密集的问题。
分库分表存在的问题:
1)事务问题 在执行分库分表之后,由于数据存储到了不同的库上,数据库事务管理出现了困难。如果依赖数据库本身的分布式事务管理功能去执行事务,将付出昂贵的性能代价,如果由应用程序去协助控制,形成程序逻辑上的事务,又会造成编程方面的负担。
2)跨库跨表的join问题 在执行了分库分表之后,难以避免会将原本逻辑关联性很强的数据划分到不同的表,不同的库上,这是,标的关联操作将会受到限制,我们无法join位于不同分库的表,也无法join分表粒度不同的表,结果一次查询能够完成的业务,可能需要多次查询才能完成
3)额外的数据管理负担和数据运算压力 额外的数据管理负担,就是数据的定位问题和数据的增删改查的重复执行问题,这些都可以通过应用程序解决,但必然会引起额外的逻辑运算,例如,对于一个记录用户乘积的用户数据表userTable,业务要求查出成绩最好的100位,在进行分表之前,只需要一个order by语句就可以搞定,但是在进行分表之后,将需要n个order by语句,分别查出每一个分表的前100名用户数据,然后再对这些数据进行合并计算,才能得出结果
读写分离和主从复制
在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的。无论是在安全性、高可用性还是高并发等各个方面都是完全不能满足实际需求的。因此,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发负载能力。
与数据切分不同的是, 这里要求所有的数据库的表结构和数据一致, 并且数据库的版本最好一致。
图片.png读写分离就是在主服务器上修改,数据会同步到从服务器,从服务器只能提供读取数据,不能写入,实现备份的同时也实现了数据库性能的优化,以及提升了服务器安全。
Mysql读写分离一般通过中间件实现:
(1)mysql_proxy。mysql_proxy是Mysql的一个开源项目,通过其自带的lua脚本进行sql判断。
(2)Atlas。是由 Qihoo 360, Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目。
(3)Amoeba。阿里巴巴开发。
主从复制的技术和原理:
可以说没有主从复制的技术就没有读写分离策略。
主从复制实现
mysq支持的复制类型
1) 基于语句的复制。在服务器上执行sql语句,在从服务器上执行同样的语句,mysql默认采用基于语句的复制,执行效率高。
2) 基于行的复制。把改变的内容复制过去,而不是把命令在从服务器上执行一遍。
3) 混合类型的复制。默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
复制的工作过程
1) 在每个事务更新数据完成之前,master在二进制日志记录这些改变。写入二进制日志完成后,master通知存储引擎提交事务。
2) Slave将master的binary log复制到其中继日志。首先slave开始一个工作线程(I/O),I/O线程在master上打开一个普通的连接,然后开始binlog dump process。binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件,I/O线程将这些事件写入中继日志。
3) Sql slave thread(sql从线程)处理该过程的最后一步,sql线程从中继日志读取事件,并重放其中的事件而更新slave数据,使其与master中的数据一致,只要该线程与I/O线程保持一致,中继日志通常会位于os缓存中,所以中继日志的开销很小。
网友评论