数据库是全部架构中不可缺乏的一环,一旦数据库出现性能问题,那对整个系统都回来带灾难性的后果。而且数据库一旦出现问题,因为数据库天生有状态(分主从)带数据(通常还不小),因此出问题以后的恢复时间通常不太可控,因此,对数据库的优化是须要咱们花费不少精力去作的。接下来就给你们介绍一下微博数据库这些年的一点经验,但愿能够对你们有帮助。算法
硬件层优化sql
这一层最简单,最近几年相信你们对SSD这个名词并不陌生,其超高的IOPS在刚出如今你们视野中的时候就让人惊艳了一把,而随着最近价格的不断下调,已经很是具备性价比,目前微博已经把SSD服务器做为数据库类服务的标配。数据库
咱们来看下咱们早些年本身对SSD的OLTP的性能测试:缓存
安全
能够看到OLTP的qps能够达到2.7w左右,配合1m2s的架构能够支持5w的qps,在一些简单场景下,甚至能够没必要配置cache层来作缓存。服务器
ps:硬件测试最好本身进行实测,官方数据仅能做为一个参考值,由于不少时候性能要严重依赖于场景,细化到不一样的SQL会获得相差很大的结论,故最好自行测试。架构
微博在12年的时候使用PCIE-FLASH支撑了feed系统在春晚3.5w的qps,在初期很好的支撑了业务的发展,为架构优化和改造争取了很是多的时间。并发
而且你们能够看到,目前不少的云厂商的物理机基本全都是SSD设备,AWS更是虚机都提供SSD盘来提供IO性能,能够预见将来IO将不会在是数据库遇到的最大瓶颈点。异步
经验:若是公司不差钱,最好直接投入SSD or PCIE-FLASH设备,并且投入的时间越早越好。async
系统层优化
配合SSD硬件以后,系统层原有的一些设计就出现了问题,好比IO scheduler,系统默认的为CFQ,主要针对的是机械硬盘进行的优化,因为机械硬盘须要经过悬臂寻道,因此CFQ是很是适合的。
Complete Fair Queuing
该算法为每个进程分配一个时间窗口,在该时间窗口内,容许进程发出IO请求。经过时间窗口在不一样进程间的移动,保证了对于全部进程而言都有公平的发出IO请求的机会。同时CFQ也实现了进程的优先级控制,可保证高优先级进程能够得到更长的时间窗口。
可是因为SSD盘已经没有了寻道而是基于电子的擦除,因此CFQ算法已经明显的不合适了,通常状况下网上都推荐使用NOOP算法,可是我我的更推荐DEADLINE算法。咱们看下这2种算法的特色。
NOOP算法只拥有一个等待队列,每当来一个新的请求,仅仅是按FIFO的思路将请求插入到等待队列的尾部,默认认为 I/O不会存在性能问题,比较节省CPU资源。 DEADLINE调度算法经过下降性能而得到更短的等待时间,它使用轮询的调度器,简洁小巧,提供了最小的读取延迟和尚佳的吞吐量,特别适合于读取较多的环境。
从算法的特色看,NOOP确实更适合SSD介质,很是的简单,可是因为数据库型服务有不少复杂查询,简单的FIFO可能会形成一些事务很难拿到资源从而一直处于等待状态,因此我的更推荐使用DEADLINE。ps:更主要的是由于对这2个算法的压测显示性能并无太明显的区别。
如下是咱们本身在线上业务调整以后的效果:

除了以上这点以外,还有一些小地方也许要调整,虽然收益不会看上去这么明显,可是积少成多,聚沙成塔,仍是很是值得优化的。
经验:重点放在针对IO的优化上,数据库尤为是MySQL是IO密集型服务,解决IO的问题会减小没必要要的问题。
MySQL自身的优化
咱们先说说有那些参数能够带来性能的改变
争议比较大,通常来讲都是在75-90之间,主要控制BP中的脏数据刷盘的时机,若是过小会频繁刷盘形成IO上升,若是太大会致使MySQL正常关闭的时候须要很长的时间才能normal shutdown,具体须要看实际场景,我的推荐90
磁盘IO吞吐,具体为缓冲区落地的时候,能够刷脏页的数量,默认200,因为使用了SSD硬盘,因此推荐设置到3000-5000
增长后台处理线程的数目,默认为4,推荐改为8
著名的双1参数,对性能影响很是的大
sync_binlog控制刷binlog的策略,MySQL在每写N次 二进制日志binary log时,会使用fdatasync()函数将它的写二进制日志binary log同步到磁盘中去。
innodb_flush_log_at_trx_commit控制log buffer刷log file的策略,设置为0的时候每秒刷新一次,设置为1的时候每次commit都会刷新。
从上述描述就能够看出若是追求数据的安全性,那么设置双一是最安全的,若是追求性能最大化,那么双0最合适,这中间能够相差至少2倍的性能。
innodb redo log的size大小,5.5最大4G,5.6最大256G,这个越大能够提高写的性能,大部分时候不须要等待checkpoint覆盖就能够一直write。
看上去很美的东西,可是在实际生产环境中,屡次给咱们带来了故障,因为每次表的更新都会清空buffer,而且对于sql的匹配是逐个字符效验实际效果很长,大部分时间并无获得cache的效果,反而获得了不少wait for query cache lock。建议关闭。
以上,仅针对MySQL 5.5,目前咱们还在摸索5.6和5.7因为尚未大规模线上使用,因此还谈不上有什么经验。
经验:若是有人力能够投入,能够学习BAT针对数据库进行二次开发,经过path的方式得到更高的性能和稳定性。若是没有人力,只要深刻了解MySQL自身参数的影响也能够知足业务的需求,不用一味的追源码级别的开发改造。
业务优化
所谓的业务优化其实说白了不少时候就是index的优化,咱们DBA常说一条慢SQL就能将上面全部的优化都付之一炬,CPU直接打满,RT全都都飙升到500ms甚至1s以上。
优化慢查有三宝:
首先,使用pt-query-digest能够定位到定位影响最中的慢查是哪条。

而后经过explain具体分析慢查晓的问题所在

重点查看type,rows和extra这三个字段。
其中type的顺序以下:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
最后,若是问题仍是比较严重,能够经过show profiling来定位一下究竟是那个环节出现的问题。

能够看到sending data最消耗时间,这时候就须要找到底为何在sending上消耗了这么多的时间,是结果集太大,仍是io性能不够了,诸如此类
如下就是一个复杂语句的优化结果,能够从rows那里明显的看出减小了不少查询的开销。

经验:最好创建慢查询监控系统,天天都花时间在慢查的优化上,避免一条SQL引起的血案之类的事情发生。
架构优化
最后,也就是终极手段了,那就是架构优化,其实不少时候,当咱们将上面几个方向都作了以后发现尚未很好的效果,那就必须找开发同窗一块儿聊一下了。ps:固然找PM同窗聊一下人生会更有效果。
记得有一次,咱们找开发聊了一下,最后开发决定将这个功能改掉,这个时候你会忽然发现不管什么优化手段都比不上「不作」这个优化手段,简直无敌了。
根据我我的的经验来讲架构层的优化有以下几个普适原则:
热点数据必须使用Redis或者mc之类的cache抗量,让MySQL抗流量是不明智的。
众所周知MySQL的异步同步机制是单线程的,全部主库上的并发到从库上都是经过io-thread来慢慢作的,即便主库写入速度再快,从库延迟了,整个集群仍是不可用,因此最好采用队列来进行必定的写入消峰,使写入维持在一个较为均衡的水平。
不少产品最开始的时候比较小,可是有可能上线以后广受好评一下用活跃度就上来了,这个时候若是数据库出现瓶颈须要拆分须要开发、DBA、架构师等等一块儿配合来作,并且颇有可能没有时间。因此在产品初期进行必定的过分设计会为将来这种状况打好铺垫。最明显的就是拆库拆表,最好在一开始就对业务进行适度的垂直拆分和比较过分的水平拆分,以便应对业务的高速增加。
举一个栗子:

经验:让合适的软件作适合的事情,不要光从技术层面思考优化方案,也要从需求方面去分解。
总结中的总结
转一篇很经典的数据库优化漏斗法则,不少年前就看到过,如今再看依然以为适用,你们共勉。

惟一不适用的就是最下的增长资源,SSD真是个好东西,谁用谁知道。