mysql 分区/分表/读写分离/分片
当数据库性能出现问题的时候,首先需要找出瓶颈,是否进行了必要的优化,如:表和字段是否建的合理,索引是否建的好,sql语句有无优化等等。
随着站点规模越来越大,数据库压力越来越大,即使做了优化也还会出现性能问题,这时我们就需要对数据库进行扩展解决性能问题。
数据库扩展的几种方式: 常用方法
- 分区(Partition)
- 分表
- 读写分离
- 分区或分片(Share Nothing)(垂直、水平分区)
- 垂直分区+水平分区
注:有些人习惯把分片称作分区,分区可以分为两种,逻辑分区和物理分区(分片),请参考:戳这里
数据拆分常用算法:
- 哈希:id % 2 = 0 对应表user_0 ,id % 2 = 1 对应表user_1
- 范围:id 1~10000000 对应表user_0 ,10000001~20000000 对应表user_1
- 映射关系:需要保存记录对应的位置信息,每次都需要先查询出对应的位置
###** 分区(Partition)** 这里的分区是指逻辑分区(Partition),MySql 有Range,List,Hash,Key 分区方法:戳这里
分表
当单表数据超过一定量时,r\w会变得很慢,read需要遍历大量数据,write需要时间建立索引;我们可以通过把这些数据分散到多个表中来提高效率,这样只涉及到部分数据而不是所有,最常用的分表方式应该是哈希。
注:分表或分区后我们就不能用数据库自增id啦~
例如:建立所需要的N个表,表名:user_0 ... user_N-1
- user_0
- user_1
- user_2
- user_3
- user_4
通过id进行哈希算法找到该id所在表名:
- 1%5:user_1
- 2%5:user_2
- 3%5:user_3
- 4%5:user_4
- 5%5:user_0
- 6%5:user_1
小结:逻辑分区是数据库提供的功能,不用对应用和业务做任何改变就能实现。哈希分表实现简单,只需要修改少量代码就能实现。对单表进行分表后,能够大大提高我们读写的效率。
读写分离
读写分离需要配置主从复制来实现,sql到达主还是从可以自己写code,也可以用代理:mysql proxy
一般站点的读操作比写操作更加密集,查询量暴增的时候单台服务器无法处理这么多读操作,我们需要增加额外的服务器来支撑,使用主从方式,主做写操作,从做读操作,通过主从复制达到数据一致性,这样读操作压力会被分散。mysql使用单线程把主机数据复制到从机上实现数据一致性,所以需要对主从进行配置。
小结:使用读写分离后,很容易通过增加服务器来提高读性能,还可以对主从服务器做高可用。(做主从之前我们还可以尝试使用cache来提高读性能)
##分区或分片(Share Nothing)
垂直分区
对于写操作频繁的站点来说,使用主从复制和读写分离效果并不明显,比如主服务器80%的时间都在写数据,那么也将花费更多的时间来同步数据,也会造成数据延迟的发生,而select查询只有20%时间处理,这时候增加从服务器也是没有效果的。对写操作这么频繁的情况,应该对写操作也进行分散。
拆分原则一般是把有关联关系的表拆分到一起,这样select join的时候不会跨节点。拆分之后,我们继续做读写分离:
水平分区
对数据库做了垂直切分和读写分离可以解决大部分站点的问题,然而当主数据库写操作压力再次达到极限,再次做垂直切分意义也不大了,还有可能会有反效果。
事实上,在考虑水平切分之前,我们一般会对数据库进行分表,它们思路是一样的:
这种方案解决了问题的同时也带来了其他问题,增加了很大的复杂度,不仅要改代码,还需要在夜深人静的夜晚,关闭站点,对数据进行计算和迁移,如果关闭时间太长或中间出了事故,用户和老板都会抱怨。如果在项目一开始就使用了分表,那么再进行水平切分就非常容易了,因为数据已经是切分好了的,所以有些业务可以考虑在一开始就这么做。
有时单一的扩展方式满足不了我们的需求,可以用多种方式进行组合。
##垂直分区+水平分区
##分片带来的问题
- 如何统一管理数据
- 引入分布式事务的问题
- 跨节点数据查询问题(如:join查询,遍历数据)
- 自增ID问题
分片优秀的中间件:mycat 国人开发,社区活跃
如不是必要,不要优先考虑分片策略,解决其带来的问题耗时耗人力难度又大,可能得不偿失。可以使用优秀的数据库中间件,难度也挺大的。
##总结 大多站点基本上都经历了从简单的读写分离到垂直分区,再到水平分区的过程,网上关于分区说的很多的一句话是“不要为了分区而分区”,根据实际情况选择不同的解决方案才是最明智的。垂直和水平分区,是一种数据规划方式,可以集中在一台服务器上的多个库中,也可以是分散在多个服务器上的多个库中。
转载于:https://my.oschina.net/zhanyu/blog/800228