数据缓存及同步数据

之前接的项目还有个有趣的需求, 是根据Id, 获得这一天之内所有关于这个Id的操作(类似于用户状态, 登录的Ip分布), 再以特定的数组形式输出到前台.即每次请求都会根据Id获取它所有的数据, 每个Id一天的数据量大概在3000条左右..我们的服务器是1M带宽, 1M内存的学生机..在MySql出现瓶颈之前, 服务器本身已经有点难以承担这个数据量了..

为了解决频繁请求数据库的问题, 于是自己写了个缓存, 本身是基于thinkphp框架写的网站:

首先获取Id和日期, 调用 cache 方法

1
2
3
4
5
6
7
8
9
class IndexController extends Controller
{
public function index()
{
$Id = I('get.Id');
$date = I('get.date')?I('get.date'):date('Y-m-d');
$cacheArray = $this->cache($date, $Id);
}
}

之后是 cache 的实现, 其中调用用于查询日期的cacheVerify函数和组合数据信息的cachePush函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private function cache($date, $Id)
{
// 分解日期
$dateArray = explode('-', $date);
// 判断年所代表的文件夹是否存在
if (!is_dir('./Public/Cache/' . $dateArray[0] . '/'))
// 不存在则生成以年命名的文件夹
mkdir('./Public/Cache/' . $dateArray[0] . '/', 0777, 1);
// 判断月所代表的文件夹是否存在
if (!is_dir('./Public/Cache/' . $dateArray[0] . '/' . $dateArray[1] . '/'))
// 不存在则生成以月命名的文件夹
mkdir('./Public/Cache/' . $dateArray[0] . '/' . $dateArray[1] . '/', 0777, 1);
// 添加以日命名的文件信息
$file = './Public/Cache/' . $dateArray[0] . '/' . $dateArray[1] . '/' . $dateArray[2] . '.json';
// 以读写形式打开, 同时基于PHP的特性, 如果文件不存在则会自动新建
$files = fopen($file, 'a+');
// 读取文件中的所有信息
$files_json = fread($files, filesize($file));
// 以 json_decode 的方法转为 array 数组
$files_data = json_decode($files_json, true);
// 调用用于查询日期下的数据是否是最新的cacheVerify函数
if (false == $this->cacheVerify($files_data, $date)) {
// 不为最新则调用生成缓存的 cachePush 函数
$query = $this->cachePush($files_data, $date, $pondId);
// 将生成的缓存数组 array 转为json,
// 同时JSON_UNESCAPED_UNICODE 变量用于将unicode转码,
// 但前提是PHP版本高于5.4
$json = json_encode($query, JSON_UNESCAPED_UNICODE);
// 将生成的缓存信息写入文件中
fwrite($files, $json);
}
// 关闭已打开的文件夹
fclose($files);
// 返回产生的缓存数组
return $query;
}

cacheVerify 的函数和cachePush 函数, 每次判断一下最新的ID和缓存中的ID是否相同, 如果相同则认为缓存是最新, 如果不同则需要更新缓存文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private function cacheVerify(array $files_data, $date)
{
$lastId = M()->query('SELECT id FROM device_data WHERE locate("' . $date . '",recv_time) ORDER BY id DESC LIMIT 1');
$files_data_end=end($files_data);
if ($files_data_end['id'] == $lastId[0]['id'])
return true;
else
return false;
}
private function cachePush(array $files_data, $date, $pondId)
{
$sql_select = '
SELECT
DATA.id,
DATA.recv_time,
FROM
device_data AS DATA
JOIN device_depend AS depend ON depend.pondId =' . $pondId . '
AND depend.deviceId = DATA.device_id
AND depend.group_id = DATA.group_id
WHERE
LOCATE("' . $date . '", recv_time)
';

$files_data_end=end($files_data);
if (!empty($files_data_end['id'])) {
$sql_select .= " AND DATA.id>" . $files_data_end['id'] . ';';
}
$query = M()->query($sql_select);
foreach($query as $key=> $value){
$query[$key]['recv_time']=str_replace($date.' ',"",$value['recv_time']);
}
if (is_array($files_data)) {
$query = array_merge($files_data, $query);
}
return $query;
}