閱讀163 返回首頁    go 阿裏雲 go 技術社區[雲棲]


php 獲取數據慢的腳本一例

背景:
今天遇到一例php連接redis獲取value時間波動的問題,在幾百毫秒到幾秒鍾不等,對於使用了redis來說這個時間確實比較久

排查:

1,檢查redis各項監控項沒有明顯的異常(qps,吞吐量,cpu)
2,檢查ecs自身的負載,內網帶寬是否存在突發的情況(一般類比其他時間段的流量峰值看看能高出多少)
3,長ping測試網絡是否有波動

php輸出毫秒級時間嚐試獲取慢在哪裏?

<?php

$host = "*****.redis.rds.aliyuncs.com";
$port = 6379;
$user = "*****";
$pwd = "*****";
$redis = new Redis();
list($s1, $s2) = explode(' ', microtime());
echo "Start_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";
if ($redis->connect($host, $port) == false) {
    die($redis->getLastError());
}
list($s1, $s2) = explode(' ', microtime());
echo "Conn_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";
if ($redis->auth($pwd) == false) {
    die($redis->getLastError());
}
list($s1, $s2) = explode(' ', microtime());
echo "Auth_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";
if ($redis->set("foo", "bar") == false) {
    die($redis->getLastError());
}
list($s1, $s2) = explode(' ', microtime());
echo "Set_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";
$value = $redis->get("foo");
list($s1, $s2) = explode(' ', microtime());
echo "Get_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";
echo "The keys value is:".$value."\n";

?>

腳本大意:
參數設置相關:

$host = "*****.redis.rds.aliyuncs.com";
$port = 6379;
$user = "*****";
$pwd = "*****";
$redis = new Redis();

輸出第一個執行時間(Start_time:腳本開始時間,前麵的變量設置這裏不計了)

list($s1, $s2) = explode(' ', microtime());
echo "Start_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";

輸出第二個執行時間(Conn_time:第二個可以理解為連接時間,如果dns解析慢,或者tcp三次握手建聯慢,都會體現在這裏)

if ($redis->connect($host, $port) == false) {
    die($redis->getLastError());
}
list($s1, $s2) = explode(' ', microtime());
echo "Conn_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";

輸出第三個執行時間(Auth_time:密碼驗證的時間消耗)

if ($redis->auth($pwd) == false) {
    die($redis->getLastError());
}
list($s1, $s2) = explode(' ', microtime());
echo "Auth_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";

輸出第四個執行時間(Set_time:set一個key value的時間)

if ($redis->set("foo", "bar") == false) {
    die($redis->getLastError());
}
list($s1, $s2) = explode(' ', microtime());
echo "Set_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";

輸出第五個執行時間(Get_time:這個時間用來計算get前麵設置的key的時間,腳本最後輸出對應的key)

$value = $redis->get("foo");
list($s1, $s2) = explode(' ', microtime());
echo "Get_time:" . date("Y-m-d H:i:s", $s2) . "." . (float) sprintf('%.0f', $s1 * 1000) . "\n";
echo "The keys value is:".$value."\n";

循環運行這個腳本

for i in {1..500};do php ali-redis-test.php;sleep 1s;done >>time.txt

這個是linux命令行直接運行的,運行500次這個php腳本,每次間隔1秒鍾,>>time.txt代表將記錄寫入這個文件

腳本運行截圖
image
配合抓包工具進行抓包,基本可以定位到慢在哪個環節,然後具體問題再具體分析

tcpdump -i eth0(內網網卡) host  r-******.redis.rds.aliyuncs.com and port 6379 -w 1.cap

最後更新:2017-09-25 20:32:49

  上一篇:go  DataX配置及使用
  下一篇:go  【MHA】命係列介紹--[masterha_master_switch]