【高同時シンプルソリューション】redisキューキャッシュ+mysql一括入庫+phpオフライン統合
需要背景:
mysqlに格納する必要がある呼び出し統計ログストレージと統計需要があります.ストレージ・データのピークは1日1千万に達し、ボトルネックは直接入庫して同時に高すぎてmysqlを潰す可能性があることです.
もんだいぶんせき
思考:応用ウェブサイトアーキテクチャの回折過程において、最新のフレームワークとツール技術を応用することはもちろん最良の選択である.しかし,既存のフレームワークに基づいて簡単に依存できるソリューションを提案できれば,自己向上の試みではないだろうか.
解決:
問題1:ログの入庫が望ましいことを要求する.しかし、直接入庫mysqlは確かに担げません.ロット入庫は問題ありません.done.【一括入庫と直接入庫の性能差異参考文献】
問題2:一括入庫には高い同時メッセージキューが必要であり、redis listシミュレーションで実現することを決定し、ロールバックを容易にする.
問題3:ログの量は結局大きくて、最近の30条を保存して十分で、phpでオフライン統計とスクリプトを整理することを決定します.
done、次はドラッグの簡単な実現過程です.
一:データベーステーブルとストレージの設計
logシステムのデータベースに対するパフォーマンスがより多く、安定性とセキュリティがそれほど高くないことを考慮すると、ストレージエンジンはselect insertのインデックスのないarchiveのみをサポートします.確かにupdate需要があればmyISAMも採用できます.
logがリアルタイムで記録されたすべてのデータであることを考慮すると、数は巨大である可能性があり、プライマリ・キーはbigintを採用し、自己増加すればよい.
logシステムは書き込みを主とすることを考慮して、統計はオフライン計算を採用して、フィールドはすべてインデックスが現れないで、一方ではデータの挿入効率に影響する可能性があるため、また読む時にデッドロックをもたらして、データの書き込みに影響します.
二:redisストレージデータ形成メッセージキュー
高同時性のため、できるだけ簡単で、直接、コードをつけます.
三:データの定期的な一括入庫.
redisメッセージキュー内のデータをタイミングで読み出し、一括入庫します.
四:オフライン天級統計とデータ・スクリプトのクリーンアップ
五:コード配置
主に配置、一括入庫スクリプトの呼び出しと天レベル統計スクリプト、crontabルーチン実行です.
まとめ:他の複雑な方法で高同時処理を行うよりも、このソリューションは簡単で効果的です.redisキャッシュによる耐圧、mysqlロット入庫によるデータベースボトルネックの解決、オフライン計算による統計データの解決、定期的なクリーンアップによるライブラリのサイズの保証.
mysqlに格納する必要がある呼び出し統計ログストレージと統計需要があります.ストレージ・データのピークは1日1千万に達し、ボトルネックは直接入庫して同時に高すぎてmysqlを潰す可能性があることです.
もんだいぶんせき
思考:応用ウェブサイトアーキテクチャの回折過程において、最新のフレームワークとツール技術を応用することはもちろん最良の選択である.しかし,既存のフレームワークに基づいて簡単に依存できるソリューションを提案できれば,自己向上の試みではないだろうか.
解決:
問題1:ログの入庫が望ましいことを要求する.しかし、直接入庫mysqlは確かに担げません.ロット入庫は問題ありません.done.【一括入庫と直接入庫の性能差異参考文献】
問題2:一括入庫には高い同時メッセージキューが必要であり、redis listシミュレーションで実現することを決定し、ロールバックを容易にする.
問題3:ログの量は結局大きくて、最近の30条を保存して十分で、phpでオフライン統計とスクリプトを整理することを決定します.
done、次はドラッグの簡単な実現過程です.
一:データベーステーブルとストレージの設計
logシステムのデータベースに対するパフォーマンスがより多く、安定性とセキュリティがそれほど高くないことを考慮すると、ストレージエンジンはselect insertのインデックスのないarchiveのみをサポートします.確かにupdate需要があればmyISAMも採用できます.
logがリアルタイムで記録されたすべてのデータであることを考慮すると、数は巨大である可能性があり、プライマリ・キーはbigintを採用し、自己増加すればよい.
logシステムは書き込みを主とすることを考慮して、統計はオフライン計算を採用して、フィールドはすべてインデックスが現れないで、一方ではデータの挿入効率に影響する可能性があるため、また読む時にデッドロックをもたらして、データの書き込みに影響します.
二:redisストレージデータ形成メッセージキュー
高同時性のため、できるだけ簡単で、直接、コードをつけます.
/***************************************************************************
*
* , redis .
* $Id$
*
**************************************************************************/
/**
* @file saveLog.php
* @date 2015/11/06 20:47:13
* @author:cuihuan
* @version $Revision$
* @brief
*
**/
// info
$interface_info = $_GET['info'];
// redis
$redis = new Redis();
$redis->connect('xx', 6379);
$redis->auth("password");
//
$now_time = date("Y-m-d H:i:s");
$redis->rPush("call_log", $interface_info . "%" . $now_time);
$redis->close();
/* vim: set ts=4 sw=4 sts=4 tw=100 */
?>
三:データの定期的な一括入庫.
redisメッセージキュー内のデータをタイミングで読み出し、一括入庫します.
/**
* redis , sql, 。
* @update 2015-11-07
*
* @Author:cuihuan
* 2015-11-06
* */
// init redis
$redis_xx = new Redis();
$redis_xx->connect('ip', port);
$redis_xx->auth("password");
//
$count = 0;
$max = $redis_xx->lLen("call_log");
// , sql
$insert_sql = "insert into fb_call_log (`interface_name`, `createtime`) values ";
//
$roll_back_arr = array();
while ($count < $max) {
$log_info = $redis_cq01->lPop("call_log");
$roll_back_arr = $log_info;
if ($log_info == 'nil' || !isset($log_info)) {
$insert_sql .= ";";
break;
}
// info
$log_info_arr = explode("%",$log_info);
$insert_sql .= " ('".$log_info_arr[0]."','".$log_info_arr[1]."'),";
$count++;
}
// ,
if ($count != 0) {
$link_2004 = mysql_connect('ip:port', 'user', 'password');
if (!$link_2004) {
die("Could not connect:" . mysql_error());
}
$crowd_db = mysql_select_db('fb_log', $link_2004);
$insert_sql = rtrim($insert_sql,",").";";
$res = mysql_query($insert_sql);
// log ;
echo date("Y-m-d H:i:s")."insert ".$count." log info result:";
echo json_encode($res);
echo "
";
//
if(!$res){
foreach($roll_back_arr as $k){
$redis_xx->rPush("call_log", $k);
}
}
//
mysql_free_result($res);
mysql_close($link_2004);
}
// redis
$redis_cq01->close();
?>
四:オフライン天級統計とデータ・スクリプトのクリーンアップ
?php
/**
* static log :
*
* @Author:cuihuan
* 2015-11-06
* */
//
$link_2004 = mysql_connect('ip:port', 'user', 'pwd');
if (!$link_2004) {
die("Could not connect:" . mysql_error());
}
$crowd_db = mysql_select_db('fb_log', $link_2004);
//
$day_time = date("Y-m-d", time() - 60 * 60 * 24 * 1);
$static_sql = "get sql";
$res = mysql_query($static_sql, $link_2004);
//
// 15
$before_15_day = date("Y-m-d", time() - 60 * 60 * 24 * 15);
$delete_sql = "delete from xxx where createtime < '" . $before_15_day . "'";
try {
$res = mysql_query($delete_sql);
}catch(Exception $e){
echo json_encode($e)."
";
echo "delete result:".json_encode($res)."
";
}
mysql_close($link_2004);
?>
五:コード配置
主に配置、一括入庫スクリプトの呼び出しと天レベル統計スクリプト、crontabルーチン実行です.
#
*/2 * * * * /home/cuihuan/xxx/lamp/php5/bin/php /home/cuihuan/xxx/batchLog.php >>/home/cuihuan/xxx/batchlog.log
#
0 5 * * * /home/cuihuan/xxx/php5/bin/php /home/cuihuan/xxx/staticLog.php >>/home/cuihuan/xxx/staticLog.log
まとめ:他の複雑な方法で高同時処理を行うよりも、このソリューションは簡単で効果的です.redisキャッシュによる耐圧、mysqlロット入庫によるデータベースボトルネックの解決、オフライン計算による統計データの解決、定期的なクリーンアップによるライブラリのサイズの保証.