您的位置:首页 > 数据库

数据库读写分离与垂直分库水平分表

2017-11-03 22:20 513 查看

读写分离

随着一个网站的业务不断扩展,数据不断增加,数据库的压力也会越来越大,对数据库或者SQL的基本优化可能达不到最终的效果,我们可以采用读写分离的策略来改变现状。读写分离现在被大量应用于很多大型网站,这个技术也不足为奇了。

读写分离简单的说是把对数据库读和写的操作分开对应不同的数据库服务器,这样能有效地减轻数据库压力,也能减轻io压力。主数据库提供写操作,从数据库提供读操作,其实在很多系统中,主要是读的操作。当主数据库进行写操作时,数据要同步到从的数据库,这样才能有效保证数据库完整性。

mysql只要是通过二进制日志来复制数据。复制的方式有两种

1.基于语句的复制:数据库会记录导致改变的查询,并将这些sql在从库上重新执行一遍。它的优点是简单,易实现,并且二进制日志文件比较紧凑,因为几十MB的数据的语句可能只有几十字节而已。并且灵活性高,列的顺序,不一致但兼容的数据类型,都可以执行,当需要修改schema的时候,可以在备库上改完提升为主库,减少宕机时间。缺点就是某些数据不能准确的复制,比如带时间戳的,或者含有某些特定函数值的。并且语句的执行必须是串行的,因此会消耗不少的锁资源。

2.基于行的复制:这种方式就是把实际的数据记录到二进制日志里,因为是把数据直接复制,所以不必担心数据正确性的问题。并且在某些情况下性能比基于语句的更快,比如group by之后插入,当组合比较少的时候,只需要插入少量数据,而基于语句的则必须扫描全表。但像如果改动以where为条件,且范围较大的时候,基于行的表现就不如语句了。但是基于行的复制不需要串行执行,也不需要建立查询,cpu占用少

mysql从5.1开始支持动态的复制算法,默认基于语句,当基于语句无法复制正确的结果时,再基于行复制。通过日志在从数据库重复主数据库的操作达到复制数据目的。这个复制比较好的就是通过异步方法,把数据同步到从数据库。

基于主从复制的可分为以下三步:

第一步是主库记录二进制日志,并且是在每次准备提交事务之前写入的日志,日记记录完毕才会提交事务。

第二步备库会启动一个工作线程不断的把主库的二进制日志拷贝到自己的中继日志中,如果追上了主库的最新日志,则睡眠,知道被主库发送信号量将其唤醒。

第三步备库的sql线程读取中继日志并在备库上执行更新操作。

读写分离就是在主从复制的基础上,将读请求交由slave服务器处理,写请求交给master服务器处理

贴一篇关于读写分离主从复制比较好的一篇博客:

http://zhangfengzhe.blog.51cto.com/8855103/1563032

垂直分库、水平分表

垂直划分

按照功能划分,把数据分别放到不同的数据库和服务器。

当一个网站开始刚刚创建时,可能只是考虑一天只有几十或者几百个人访问,数据库可能就个db,所有表都放一起,一台普通的服务器可能就够了,而且开发人员也非常高兴,而且信心十足,因为所有的表都在一个库中,这样查询语句就可以随便关联了,多美的一件事情。但是随着访问压力的增加,读写操作不断增加,数据库的压力绝对越来越大,可能接近极限,这时可能人们想到增加从服务器,做什么集群之类的,可是问题又来了,数据量也快速增长。

这时可以考虑对读写操作进行分离,按照业务把不同的数据放到不同的库中。其实在一个大型而且臃肿的数据库中表和表之间的数据很多是没有关系的,或者更加不需要(join)操作,理论上就应该把他们分别放到不同的服务器。例如用户的收藏夹的数据和博客的数据库就可以放到两个独立的服务器。这个就叫垂直划分(其实叫什么不重要)。



当博客或者收藏夹的数据不断增加后,应该怎么办,这样就引出了另外一个做法,叫水平划分。

水平划分

则把一个表的数据划分到不同的数据库,两个数据库的表结构一样。怎么划分,应该根据一定的规则,可以根据数据的产生者来做引导,上面的数据是由人产生的,可以根据人的id来划分数据库。然后再根据一定的规则,先获知数据在哪个数据库。

其实很多大型网站都经历了数据库垂直划分和水平的划分的阶段。其实这个可以根据经验来确定,不一定由某些硬性的规则。

以刚才的博客为例,数据可以根据userid的奇偶来确定数据的划分。把id为基数的放到A库,为偶数的放B库。



这样通过userId就可以知道用户的博客的数据在哪个数据库。其实可以根据userId%10来处理。还可以根据著名的HASH算法来处理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据库 mysql 优化