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