Memcached 海量数据 分片存储 (未完)
最近公司在一个项目上遇到了一个问题: 对于查 海量数据的sql, 往往花费了十几秒, 甚至更多. 结果是什么呢? 首先占了mysql很多的处理数, 这个倒不是特别大的事. 系统不至于崩溃. 但它占
最近公司在一个项目上遇到了一个问题: 对于查 海量数据的sql, 往往花费了十几秒, 甚至更多. 结果是什么呢? 首先占了mysql很多的处理数, 这个倒不是特别大的事. 系统不至于崩溃. 但它占用了cpu巨大的处理量, 这会导致系统崩溃, 服务器瘫痪.
有没有什么办法来解决这种巨大数据量的sql 呢? 我先是想到了内存, 毕竟内存读取数据比硬盘要快得多. 接着开源项目memcached就成了首选了.接下来看看怎么解决这个问题吧.
memcached我就不多介绍了, google搜吧, 一大把.主要关心的是它的key=>value 存储方式 和 slab chunk内存分片的管理. 这里主要讨论key=>value 存储方式. key 是 value的数组标示, 这有点像php的数组, arr['one'] = 1;one就是key 1就是value. 只能是一一对应.
公司的情况是比如说s1 = "select * from huge_info_table where time>2011-01-01 and time<=2012-01-01", 每次s1的time范围不同, 可能没交集 也 可能有交集. s1就是key, 它的查询结果就是value. 显然按每条sql来当做key, 内存里会有很多重复的数据, 原因是time有交集. 因此, 怎么管理好key就是关键.
按整天的sql来存储key, 每当一堆key被保存. 再一次取的时候, 如果有交集部分, 也就是有已经保存过的, 就直接从memcache里面取. 如果没有就否则将key重新存进去.
s1 = "select * from huge_info_table where time>2011-01-01 and time<=2011-02-01"
s2 = "select * from huge_info_table where time>2011-02-01 and time<=2011-03-01"
s3 = "select * from huge_info_table where time>2011-03-01 and time<=2011-04-01"
有没有什么办法来解决这种巨大数据量的sql 呢? 我先是想到了内存, 毕竟内存读取数据比硬盘要快得多. 接着开源项目memcached就成了首选了.接下来看看怎么解决这个问题吧.
memcached我就不多介绍了, google搜吧, 一大把.主要关心的是它的key=>value 存储方式 和 slab chunk内存分片的管理. 这里主要讨论key=>value 存储方式. key 是 value的数组标示, 这有点像php的数组, arr['one'] = 1;one就是key 1就是value. 只能是一一对应.
公司的情况是比如说s1 = "select * from huge_info_table where time>2011-01-01 and time<=2012-01-01", 每次s1的time范围不同, 可能没交集 也 可能有交集. s1就是key, 它的查询结果就是value. 显然按每条sql来当做key, 内存里会有很多重复的数据, 原因是time有交集. 因此, 怎么管理好key就是关键.
按整天的sql来存储key, 每当一堆key被保存. 再一次取的时候, 如果有交集部分, 也就是有已经保存过的, 就直接从memcache里面取. 如果没有就否则将key重新存进去.
s1 = "select * from huge_info_table where time>2011-01-01 and time<=2011-02-01"
s2 = "select * from huge_info_table where time>2011-02-01 and time<=2011-03-01"
s3 = "select * from huge_info_table where time>2011-03-01 and time<=2011-04-01"
<?php
require("dblib.php");
define("START_TIME", 5);
define("END_TIME", 7);
function formatQueryString($query){
$array_result = explode(' ', $query);
//取请求的sql语句, 分隔成array数组, 对N个小时的请求
sscanf($array_result[START_TIME], "begin_time>'%d-%d-%d'", $s_year, $s_mouth, $s_day);//开始时间
sscanf($array_result[END_TIME], "begin_time<='%d-%d-%d'", $e_year, $e_mouth, $e_day);//结束时间
if($s_day!=1&&$e_day!=1){
print("Sql warning, day of datetime must be 1");
$s_day = $e_day = 1;
}
while($s_year!=$e_year||$s_mouth!=$e_mouth){
if($s_mouth == 12){
$arr[] = sprintf("select * from session_detail where begin_time>'%02d-%02d-%02d' and begin_time<='%02d-%02d-%02d'",
$s_year, $s_mouth, $s_day,
$s_year+1, 1, $e_day);
$s_mouth = 1;
$s_year++;
}else if($s_mouth < 12){
$arr[] = sprintf("select * from session_detail where begin_time>'%02d-%02d-%02d' and begin_time<='%02d-%02d-%02d'",
$s_year, $s_mouth, $s_day,
$s_year, $s_mouth + 1, $e_day);
$s_mouth++;
}
}
print_r($arr);
return $arr;
}
function cacheRepair($memcache, $key, $link, $hold_time){
$array_result = formatQueryString($key);//取得每天的sql当做key
foreach($array_result as $sqlofday){
if($memcache->add($sqlofday, NULL, 0, 30)){
//如果当前这一天的key不存在
$res = dbQuery($sqlofday, $link);
$memcache->set($sqlofday, gzcompress(serialize($res)), FALSE, $hold_time);
echo "<br>Key:\"".$sqlofday."\"[Mysql]";
}else{
echo "<br>Key:\"".$sqlofday."\"[Memcached]";
}
}
}
$memcache = new Memcache;
$memcache->connect("localhost", 11211);
$link = dbConnect("192.168.230.231", "ccone", "ccone", "ccone");
cacheRepair($memcache, 'select * from session_detail where begin_time>\'2012-01-01\' and begin_time<=\'2012-03-01\'', $link);
?>
2. [文件] dblib.php ~ 728B 下载(10) 跳至 [1] [2] [全屏预览]
<?php
/* dbConnect
* host: ip;
* name: mysql user;
* passwd: user's passwd;
* db: database
*/
function dbConnect($host, $name, $passwd, $db){
if(!$link = mysql_connect($host, $name, $passwd)){
printf('Connect to %s[name:%s passwd%s] failed.', $host, $name, $passwd);
exit(-1);
}
if(!mysql_select_db($db, $link)){
printf('No such database which name is %s.', $db);
exit(-1);
}
return $link;
}
/* dbQuery
* sql: select query
*/
function dbQuery($sql, $link){
if(!$result = mysql_query($sql, $link)){
echo mysql_errno($link) . ": " . mysql_error($link) . "\n";
return FALSE;
}else{
while ($row=mysql_fetch_assoc($result)){
$arr[]=$row;
}
return $arr;
}
}
?>
精彩图集
精彩文章






