一、最好的優化-----不查詢!
這不是開玩笑.
如果一臺服務器出現長時間負載過高 /週期性負載過大,或偶爾卡住,如何來處理?
大的思路--------
是週期性的變化還是偶爾問題?
是服務器整體性能的問題, 還是某單條語句的問題?
具體到單條語句, 這條語句是在等待上花的時間,還是查詢上花的時間.
唯一的辦法-----監測並觀察服務器的狀態.
1:觀察服務器狀態, 一般用如下2個命令
Show status; Show processlist;
例: mysql> show status;
#mysqladmin ext (功能相同)
二、那我們來做一個實驗:MySQL週期性波動試驗
(一)、實驗目的: 模擬數據庫高低峯時的壓力波動,並會觀察繪製波動曲線
(二)、實驗思路: 反覆查詢數據庫並緩存入memcached, 緩存定期失效,
(三)、觀察記錄服務器參數,並作圖表.
(四)、實驗準備: nginx+php+memcached+awk+ab
1: index.php (隨機訪問3W條熱數據,並儲存在memcached中
2: memcached (儲存查詢結果)
3: ab 壓力測試工具
4: awk腳本
三、實驗步驟:
總數據1300W以上,熱數據3W,50個併發,每秒請求500-1000次
請求結果緩存在memcache,生命週期爲60秒,
(生命週期要結合請求週期來制定,比如3萬條數據隨機,每秒1000條,30秒能走一遍,生命週期可設爲60秒)
觀察mysql連接數,每秒請求數的週期變化.
再打開一個窗口
50個併發,200000個總請求
緩存熱數據腳本
<?php
// 30K hot news
$rangeid = rand(1,30000)+13000000;
$mconn = memcache_connect('localhost',11211);
if( ($com = memcache_get($mconn,$rangeid)) === false) {
$conn = mysql_connect('localhost','root');
$sql = 'use bigdata';
mysql_query($sql,$conn);
$sql = 'set names utf8';
mysql_query($sql,$conn);
$sql = 'select id,name,brief from lx_com where id=' . $rangeid;
$rs = mysql_query($sql,$conn);
$com = mysql_fetch_assoc($rs);
memcache_add($mconn , $rangeid , $com , false, mt_rand(40,120));
} else {
echo 'from cache';
}
print_r($com);
統計腳本status.sh
#!/bin/bash
while true
do
mysqladmin -uroot ext|awk '/Queries/{q=$4}/Threads_connected/{c=$4}/Threads_running/{r=$4}END{printf("%d %d %d\n",q,c,r)}' >> status.txt
sleep 1
done
讓memcached後臺運行
ab壓力測試
在Excel畫出圖表
解決辦法:
1: 減少無關請求(業務邏輯層面,暫不討論,但其實是最有效的手段)
2: 如果請求數是一定的,不可減少的. 我們要儘量讓請求數平穩,不要有劇烈波動.
很多時候,不是服務器撐不住總的查詢量,而是在某個時間段撐不住高峯請求.
----夜間負載低時,集中失效.
短時間內會有波峯,但夜間訪問量少,因此波峯並不劇烈,當到上午10點左右人多時,緩存已經建立了一部分. 白天時,波峯也不劇烈.
或者讓緩存的生命週期在一定範圍內隨機,也可以減緩波峯劇烈的情況
我們把實驗中的生命週期由80秒,改爲[40-120秒],其他實驗條件不變.
得到如下曲線
可以看出,穩定運行後,請求在[1000-1500]之間波動,
而固定緩存週期是,請求在[500-1700]之間波動.