龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > php编程 >

Memcached 海量数据 分片存储 (未完)

时间:2014-07-22 14:51来源: 作者: 点击:
分享到:
最近公司在一个项目上遇到了一个问题: 对于查 海量数据的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"

<?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;
	}
}
?>
精彩图集

赞助商链接