数据库层面:前端
应用系统层面优化
node
SQL优化mysql
SQL优化通常经过分析慢查询日志来抓取长事务高消耗的sql,经过结合具体业务,对sql逻辑进行分析and精简,or重写sql。经过配置slow_query_log=1和log_queries_not_using_indexes=1启动慢查询日志记录和记录下没有使用索引的查询,后者会让慢查询日志文件很快膨胀,须要定时对文件进行切割。分析慢日志的工具通常使用pt工具包的pt-query-digest或者mysql自带的mysqldumpslow,我的比较倾向用pt,分析出来的内容比较详细。须要注意pt-query-digest实际上是一个perl脚本,若是慢日志文件较大(几G多),须要大量消耗CPU资源。建议在业务低峰时候调度该工具。linux
索引优化算法
索引是数据库最为常见的对象。基本上90%的sql性能问题都是没有建索引or低效索引致使的。因此根据实际业务场景建合适的索引,可以使得sql优化事半功倍。sql
索引的设计规则:选择惟一性索引or主键;为常常须要排序、分组和联合操做的字段创建索引,尽可能创建复合索引而非单列索引;为常做为查询条件的字段创建索引;限制索引的数目;尽可能使用数据量少的索引;尽可能使用前缀来索引;删除再也不使用或者不多使用的索引。mongodb
建立索引的一些注意事项:数据库
(1)避免在where子句中使用!=或者<>操做符,不然引擎会放弃索引而进行全表扫描缓存
(2)避免在where子句中使用or来链接条件,考虑用union代替。服务器
(3)避免在where子句中对字段进行表达式操做或者函数操做
(4)先应考虑在 where 及 order by 涉及的列上创建索引
(5)在使用索引字段做为条件时,若是该索引是复合索引,那么必须使用到该索引中的第一个字段做为条件 时才能保证系统使用该索引, 不然该索引将不被使用,而且应尽量的让字段顺序与索引顺序相一致。即最左原则。
(6)索引当然能够提升相应的 select 的效率,可是也须要成本去维护索引,所以表的索引个数并不是越多越好,通常不要超过7个。
(7)若是使用到了临时表,在最后将全部的临时表显式删除时,先 truncate table ,而后 drop table ,这样能够避免系统表的较长时间锁定。
(8)避免频繁建立和删除临时表,以减小系统表资源的消耗。对于一次性事件, 最好使用导出表。
(9)最好不要给数据库留NULL,尽量的使用 NOT NULL填充数据库.备注、描述、评论之类的能够设置为 NULL,其余的,最好不要使用NULL。
(10)对于varchar的字段建立索引,指定索引长度,避免建立全字段索引,能够经过count(distinct left(列名,索引长度))/count(*)计算区分度来肯定索引长度。
(11)多表关联查询的时候,必须保证关联的字段有索引。并且字段的类型必须一致,避免因为隐式转换致使索引失效。
库表优化
举个例子:业务前期不注重表设计,致使日志、报文、图片这类数据都经过表的方式存储在数据库。而这类数据通常是经过text/blob等类型的字段存储,极易使得表容量暴增,并且很难去优化这类表的查询sql。须要作好库表设计,对图片、报文这类数据,改成经过mongodb等NOSQL数据库进行存储。或者将表的部分大字段进行拆分,单独出来一个表,经过冗余部分字段,实现表与表之间的数据关联(不建议经过mysql的外键约束实现关联,由于在高并发的状况下,会出现大量行锁影响数据库性能,强烈建议经过应用程序实现数据关联。)
采用统一的字符集和校验集,使用innodb引擎,表设计中采用与业务无关的自增ID列做为主键,减小存储过程and自定义函数,尽可能不用text/blob这类字段类型。
表设计规范
请参考附件 阿里巴巴Java开发手册 和 58到家数据库30条军规解读 (https://www.oschina.net/question/54100_2231325)
数据库对象优化
内存配置优化
innodb缓冲池设置:innodb_buffer_pool_size,通常为整机内存的70%~80%
缓冲池脏页占比:innodb_max_dirty_pages_pct,默认为75%,建议按照业务场景进行设置。
强烈建议关闭query cache。经过配置文件设置query_cache_size = 0、query_cache_type = 0便可。
redo log缓冲区设置:innodb_log_buffer_size,若是没大事务,控制在8M-16M便可,生产环境目前配置到64M。
IO配置优化
sync_binlog:
sync_binlog=0,当事务提交以后,MySQL不作fsync之类的磁盘同步指令刷新binlog_cache中的信息到磁盘,而让Filesystem自行决定何时来作同步,或者cache满了以后才同步到磁盘。
sync_binlog=n,当每进行n次事务提交以后,MySQL将进行一次fsync之类的磁盘同步指令来将binlog_cache中的数据强制写入磁盘。
sync_relay_log:
同sync_binlog参数功能同样,只不过对象是relay log而不是binlog。
innodb_flush_log_at_trx_commit:
若是innodb_flush_log_at_trx_commit设置为0,log buffer将每秒一次地写入log file中,而且log file的flush(刷到磁盘)操做同时进行.该模式下,在事务提交的时候,不会主动触发写入磁盘的操做。
若是innodb_flush_log_at_trx_commit设置为1,每次事务提交时MySQL都会把log buffer的数据写入log file,而且flush(刷到磁盘)中去.
若是innodb_flush_log_at_trx_commit设置为2,每次事务提交时MySQL都会把log buffer的数据写入log file.可是flush(刷到磁盘)操做并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操做。
sync_master_info:
每间隔多少事务刷新master.info,若是是table(innodb)设置无效,每一个事务都会更新
sync_relay_log_info:
每间隔多少事务刷新relay-log.info,若是是table(innodb)设置无效,每一个事务都会更新
master_info_repository:
记录主库binlog的信息,能够设置FILE(master.info)或者TABLE(mysql.slave_master_info)
relay_log_info_repository:
记录备库relaylog的信息,能够设置FILE(relay-log.info)或者TABLE(mysql.slave_relay_log_info)
innodb_io_capacity:默认为200,若是是SSD盘,建议调整到5000
高并发设置
扩大文件描述符:
一、动态修改,重启失效,只能使用root,而且当前session有效:ulimit -n 65535
二、修改配置文件,永久生效,在/etc/security/limits.conf配置文件中增长:
* soft nofile 65535 * soft nproc 65535 * hard nofile 65535 * hard nproc 65535
主机层面:
一、CPU
将其调整为性能模式,即:performance,能够参考博客:http://blog.csdn.net/myarrow/article/details/7917181/
二、内存
(1)关闭NUMA特性。NUMA陷阱现象是当你的服务器还有内存的时候,发现它已经在开始使用swap了,甚至已经致使机器出现停滞的现象。这个就有多是因为numa的限制,若是一个进程限制它只能使用本身的numa节点的内存,那么当自身numa node内存使用光以后,就不会去使用其余numa node的内存了,会开始使用swap,甚至更糟的状况,机器没有设置swap的时候,可能会直接宕机。因此,强烈建议在操做系统层面关闭NUMA特性。直接在/etc/grub.conf的kernel行最后添加numa=off便可。
(2)尽可能配置高内存。这种mysql能够充分利用内存资源缓存热块数据,避免因为内存不足致使脏数据不断地刷盘从而产生IO瓶颈,也能够避免热块数据被挤出缓存区的状况发生。
(3)修改swappiness设置。swappiness是linux的一个内核参数,用来控制物理内存交换出去的策略.它容许一个百分比的值,最小的为0,最大的为100,改值默认是60.m.swappiness设置为0表示尽可能少使用swap,100表示尽可能将inactive的内存页交换到swap里或者释放cache。inactive内存的意思是程序映射着,可是”长时间”不用的内存。这个值推荐设置为1,设置方法以下,在/etc/sysctl.conf文件中增长一行:vm.swappiness = 1
三、磁盘IO
(1)尽可能将数据文件和日志文件分开,各自承载相应的磁盘。避免日志刷盘和数据刷盘之间争用IO。
(2)尽可能使用高IO的磁盘,或者使用raid10这类磁盘阵列,或者直接采用SSD盘
四、网络优化
集群内机器最好部署在同一内网or专线直连的网络环境,以保证低延迟,高吞吐的网络环境。避免因为网络问题致使的集群内脑裂or主从复制异常的状况。
操做系统层面:
一、文件系统
强烈建议采用xfs文件系统,ext4文件系统存在bug,触发会占用自身大部分IO,形成IO瓶颈。详见http://1057212.blog.51cto.com/1047212/1891734
优化文件系统挂载参数:文件系统挂载参数是在/etc/fstab文件中修改,重启时候生效。noatime表示不记录访问时间,nodiratime不记录目录的访问时间。barrier=0,表示关闭barrier功能。其中nobarrier是xfs文件系统特有,ext4文件系统并没有此参数。
二、IO调度算法
NOOP:NOOP算法的全写为No Operation。该算法实现了最最简单的FIFO队列,全部IO请求大体按照先来后到的顺序进行操做。
CFQ:CFQ算法的全写为Completely Fair Queuing。该算法的特色是按照IO请求的地址进行排序,而不是按照先来后到的顺序来进行响应。
DEADLINE:DEADLINE在CFQ的基础上,解决了IO请求饿死的极端状况。除了CFQ自己具备的IO排序队列以外,DEADLINE额外分别为读IO和写IO提供了FIFO队列。读FIFO队列的最大等待时间为500ms,写FIFO队列的最大等待时间为5s。FIFO队列内的IO请求优先级要比CFQ队列中的高,,而读FIFO队列的优先级又比写FIFO队列的优先级高。优先级能够表示为:FIFO(Read) > FIFO(Write) > CFQ
通常mysql服务器的磁盘IO调度算法采用deadline,既能够保证IO请求不被饿死,又可使得读IO的处理优先级大于写IO。
系统架构层面优化
负载均衡
这里能够分为两类:
一、PXC or mysql cluster or mysql group replication这类数据库集群,因为支持多点写入的方式,这里的负载均衡能够实现读和写都均衡负载的状况,经过在数据库前端部署haproxy或者LVS的方式实现负载均衡。可是须要强调的是,目前这类型集群在多点写入的状况很容易产生锁冲突和更新丢失的状况,通常官方建议开启单点写入。也就是说,通常也只能实现单节点承载写操做,剩余节点均衡负载读操做。
二、mysql一主多从架构:因为主库必须单独承载写操做,故均衡负载只是针对于读操做。也是经过在数据库前端部署haproxy或者LVS的方式实现读操做负载均衡。
缓存
通常采用内存数据库如Redis、memcached同mysql结合,将热点数据放在内存数据库上实现高并发。能够参考博客:http://blog.csdn.net/stubborn_cow/article/details/50586990
分布式优化
分库分表:
这里也能够分为2类:
(1)经过前端应用代码逻辑实现的方式,实现表分拆的方式。这样作对应用程序的侵入性比较大,可是数据处理逻辑的过程把控在本身手上,有异常能够自主定位。
(2)经过中间件的方式实现,目前经常使用的mycat、cobar实现数据分片。
读写分离:
通常经过数据库中间件的方式实现,经常使用的中间件例如:maxscale、mycat、cobar、altas等