數據庫層面:前端
應用系統層面優化
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等