关于mysql分库分表及高可用集群经验 [上]

    照我风格,总是喜欢聊一下让人觉得废话连篇的前言语句, 但由于最近工作和家庭的事情实在太忙,tm身心疲惫,今后也尽量少嘚嘚,直接抛开话题。 

   话说我个人一直都想往架构方面转,认为自己运维、运维开发、底层开发、业务开发都做过,微观和大局观总是高人一等,但事实往往不是这样子。  贪多不烂, 艺多不精是我现在的问题。 没招,只能慢慢搬砖打磨自己。 

   现在每天都在花时间总结自己以往的经验及新的知识点的扩展学习,总之一直在学习在进步中。  前段时间在社区的朋友,让我讲讲 mysql分库分表及高可用集群方面的经验。  虽然我个人是有项目的分库分表经验,但业务类型会跟大家不一样的, 我尽量把场景覆盖的全面一些。

该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新.  

 http://xiaorui.cc/?p=3883

下面我们会一个个的分析实际mysql分库分表中遇到的一些场景问题。  可能有些论点显得有些不合时宜,请大家指点

 

如果在业务上需要强一致性,就算有主从环境:

第一.   直接强一致性,  业务读写都在Master上.  

优点, 开发简单.   缺点,  性能呀, slave只能做备机了.


第二.   主从不一致时,可以通过中间件时间窗口解决,比如某个 id 被改了, 我可以在中间层做个标记,应用从中间件访问时碰到id被修改了,那么走主。  ( 当然不单单可用 id 做标记)


多个冗余表入库场景:
( 多个冗余表的意思是,为了解决某个多维度分表的问题 )


第一   不加事物,单纯同步阻塞的方式写两个表.       

缺点, 首先是性能的问题,其次是中间宕机, 那么其他的冗余表没法入库。


第二   使用分布式二次提交的方法 ( 2pc , 3pc) 保证入库.   

缺点, 开发的逻辑有些麻烦,需要维护多个事物。

第三   消息写入,消息校验.                

纯异步,性能没的说,靠不靠谱就要看消息队列的ha能力了。


除了那种支付金融业务,其余的场景, 这一二三都可以用的,那么缺数据怎么办?  我们可以写个定时服务脚本来修复多表的一致修复. 

如果涉及到关键数据,推荐使用分布式事物2pc, 3pc, 更高端的消息系统事物的解决方法。  如果想多了解2pc的实现,可以翻找下我以前的博客。


业务数据缓存问题:
(还是数据不一样问题,这次跟上面主从类似,缓存数据不够新)


第一  当写请求处理时,  缓存可以同步或异步方法刷新.  也就是说,当数据改变时,才会去被动更新.


第二  缓存强制超时,  不会因为hit命中缓存而延续时间,  脏数据存在时间是有限制的.

第三  写密集时,可以适当用sorted set延迟5s 执行.


数据分表之后的分布式分页查询问题:

(因为热点及增删改过大的问题, 采用了hash分区.  但这样子之后,鬼知道数据跑哪里去了)


第一    如果是hash分的,业务上对于精度又不在乎,比如 limit 100 的需求, 我们可以分别在五个表进行 limit 20,各搜 20个.


第二    对于数据精准度较高标准做法是 跨库表查询,在中间层聚合重排序缓存。 当然这样消耗性能 ! !!

第三    除了第一次请求使用limit n,后面的请求都附带上次最大的id, 优化后的语句是  where id > last_id limit n .

对于经常分页查询的数据,还是尽量减少使用hash的方式.   互联网95%的流量都是读流量,过大的读请求可以使用从集群解决。 但对于上述的那种DML性能瓶颈问题, 咱们可以使用 分组+ 分片的方式进行, 我后面会好好的陈述下这种分表结构的优缺点。


分库分表之前的一些努力 ? 不白扯 !

第一, 结合explain和慢查询,优化你的sql和索引;  

第二, 应用级别可以加缓存, redis,memcached,aerospike都可以;

第三, 如果查询的量级过大,就要做主从复制或主主复制,读写分离,可以在应用层或者mysql中间层实现;

第四, 垂直拆分,根据你的业务情况把热点的表拆出分库分表;

第五, 终极绝招,水平切分 ! 选定一个sharding key, 进行分库分表 !

中间其实可以在加一个步骤,就是hhd vs ssd的升级 !!!提升硬件的效果是相当喜人的,一个200 iops 和 几万的iops … 
另外单表尽量控制到 一千万左右, 单库的表尽量控制在500左右. 
mysql解决性能的路数一般都是按照这个步骤去演化的,成本也是由低到高; 除非你们觉得数据后期会暴增,那么可以一起进行 !!! 


为什么我们要分库分表?

有种种的原因,希望大家为了良心,不让后人因为这瓶颈问题而被人嘴上伺候爹妈了.   一般来说原因不外乎就这么几种? 

第一, 分库分实例后绝对好维护.
第二, 数据量大,时常会锁,检索数据慢,维护也是个坑 
第三, 因抗拒数据不一致,流量都在master, 导致单master压力过大.

第四, 就是写大.

第五, 肯定还有…

这几个原因总结就一句话,不好维护,性能太渣. 


如何选择分库分表的方案

第一种 , 范围分表. 

这个范围你可以是id范围,也可以是时间等等。 他的优点是开发比较简单, 但缺点也能想到,就是数据的热点过于集中,相对别的区间数据是否均匀也是个问题.  range分表总之各有利弊吧,主要还是看业务。


第二种, hash取模分表.

这一种相对公平的分表方式,md5(xxx) % 8 ,  但他的缺点就是扩容是相当的麻烦的,要重新简单迁移数据。


第三种, range范围 +  hash

可以想成raid10的磁盘阵列算法,他的优点是为了解决第一种方法中 单区间分表 热点的问题.  我们可以把某个区间进行再次hash到N个表.


第四种,一致性hash分表

这个适合的场景很多,但偏向于数据多的场景,想怎么扩展就怎么扩展。 sid = md5(xxx) % 5000 ;  [{‘range’: (0,512), ‘master_db’: ‘xxx’}, {‘range’: (513: 1024)} … …]

对于那种论坛新闻性质的需求,他有新帖跟老帖之分的, 比如好几年的帖子很少有人关注了,你可以做一些归档处理,所谓的归档就是存起来就行了,不求性能.    像这类明显有新老破旧之分的分表需求,你可以使用range分区,或者range + hash.

对于那种量级大,又要保证读写性能的需求,可以使用hash取摸分表 和 一致性hash分表.   hash mode是一定程度上的随机性. 那么量级大又怎么一回事? 看下面 !

其实跟dba的朋友聊了很多,对于不可估量的分库分表,一开始就要选择好后期可扩容的架构.   尤其对于那种不可控的业务暴增场景,一开始就要给他上多分库多分表.  


以前在乐视的时候,经常有人跑到我工位周边的dba问”将来”扩容的问题,首席dba工程师都会强硬给你建立512个表,或者1024个表…   对于有mysql中间件的公司,不管分多少库表,跟你做业务的都没啥大关系….


这里额外提一句,在分库分表的场景下,尽量要用mysql的中间件 !  我想当大家到了那种量级,自然也能搞的定。  那么我为什么会推荐大家使用mysql 中间件 ?  如果你是程序控制连接池,那么每次更新db config要反复上线。当然你可以说 用zookeeper做了配置管理,那么当你的应用得到zookeeper更新时,你该如何调整现有的连接池 ?   对于那种跨库join的sql语句,你需要同步模式一个个的遍历结果,然后聚合return ?  等等…    现在互联网公司在分库分表面前,大多会选择 mysql 代理的.   当然代理的性能瓶颈肯定是有的.  现在市面上还没有特别可靠的mysql proxy,只能找个模子二次开发了。  


这里我做个广告,代理方面建议大家用下 陈非同学的kingshard.   这哥们当初360安全搞atlas proxy的时候,我就认识他了,靠谱小哥….  有时间我会专门抽出几个章节来聊聊 mysql proxy那些事,不单单是成名的中间件,因为当初看过kingshard的源码,正好顺带讲点设计实现原理… 

END … …


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

1 Response

  1. 2016年11月3日 / 下午3:13

    干货 介绍下mysql各种中间件吧

发表评论

邮箱地址不会被公开。 必填项已用*标注