SAE开发:利用memcache优化数据库读取

回复 星标
更多
SAE开发:利用memcache优化数据库读取
.
.
.
.
.
.

237327

SAE调整了新收费规则后,mysql变成了按次数收费(之前是按CPU时间收费)。本文将与大家共同探讨如何利用memcache来优化数据库读取,减少mysql读取次数,降低成本的同时增加程序效率。

适读人群:具有初级以及初级以上开发能力的PHP开发者。

开始前,请记住我们要做的是:减少mysql读取次数

Memcache是SAE为开发者提供的分布式缓存服务,用来以共享的方式缓存用户的小数据。它速度快,云豆消耗低,存储简单,因此非常适合用来缓存数据库读取结果。

在一般应用中,我们最常用的是两种数据库查询:一种是读取单表的一条记录,一种是读取单表的多条记录。针对这两种情况,我们可以做专门封装两个数据库操作函数:一个是快速读取单条记录get_row(),一个是读取多条记录get_rows();然后,我们在这两个函数的基础上,再封装成另一个使用了memcache的函数。看下面代码(配合注释看):

<?php
$GLOBALS['mmc'] = memcache_init();//初始化memcache
db_connect();//连续数据库
//连接数据库函数
function db_connect()
{
    $conn=mysql_connect( SAE_MYSQL_HOST_M.":".SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
    $db_s=mysql_select_db(SAE_MYSQL_DB);
    if($db_s)return $conn;
    else return false;
}
//根据字段快速返回一条记录数组
function get_row($value="uid",$field="uid",$table="users")
{
    $sql="select * from $table where $field='$value' limit 1 ";
    $result=mysql_query($sql);
    if(mysql_num_rows($result))
    {
        $row=mysql_fetch_array($result);
        if($row){return $row;}
    }
    return false;
}

//运行Sql,以多维数组方式返回结果集
function get_rows($sql){
    $ary=array();
        $result=mysql_query($sql);
        if(mysql_num_rows($result))
        {
                while($row=mysql_fetch_array($result))
                {
                    $ary[]=$row;
                }
        }
        return $ary;
}
//使用了Mencache的get_row()。默认缓存24小时
function get_row_cache($value,$field,$table,$time = 86400)
{

    $row=memcache_get($GLOBALS['mmc'], 'row_cache_'.$value.$field.$table);
    if(!$row)//如果这个值非真,即为空的话,则从数据库读取
    {
        $row = get_row($value,$field,$table);
        if($row){
             $ret = memcache_set($GLOBALS['mmc'],'row_cache_'.$value.$field.$table, $row , 0, $time);//写进mc,默认有效期为24小时
        }
    }
    return $row;
}
//使用了Mencache的get_rows()。默认缓存24小时
function get_rows_cache($sql ,$time = 86400)
{
    $sql2 = base64_encode($sql);
    $rows = memcache_get($GLOBALS['mmc'], 'rows_cache_'.$sql2);
    if(!$rows)//如果这个值非真,即为空的话,则从数据库读取
    {
        $rows = get_rows($sql);
        if($rows)memcache_set($GLOBALS['mmc'],'rows_cache_'.$sql2, $rows , 0, $time);//写进mc,默认有效期为24小时
    }
    return $rows;
}
//删除 get_row_cache()的缓存
function delete_row_cache($value,$field,$table)
{
    memcache_delete($GLOBALS['mmc'], 'row_cache_'.$value.$field.$table);
}
//删除 get_rows_cache()的缓存
function delete_rows_cache($sql)
{
    $sql2 = base64_encode($sql);
    memcache_delete($GLOBALS['mmc'], 'rows_cache_'.$sql2);
}
?>

以后调用的时候,只需要使用函数get_row_cache()和get_rows_cache()即可。更新缓存的时候可以调用delete_row_cache()和delete_rows_cache().

别以为有了代码,我们的优化目标就达到了。代码只是技术实现手段,真正重要的是它背后的策略。甚至说哪位朋友把我上面的代码用另一种方式重写也毫无压力。我想在这里分享的不只是代码,还有优化策略。

1、“重新生成缓存”这一步操作,要放到get_row_cache()里面,而不是delete_row_cache()里。有同学习惯在删除缓存的同时生成缓存。这是有风险的。因为memcache有几率会丢失数据,或者被后台清空。把“重新生成缓存”放在get_row_cache()里,可以避免memcache里没有数据的风险(没有数据的时候,程序会在get_row_cache()里重新生成缓存)

2、get_row_cache()不要用来判断数据库某条记录存在不存在。例如可能有同学在程序中,需要判断网站用户是否在黑名单里。于是就调用get_row_cache()来判断uid是否存在backlist表里。这会拖慢效率的,因为memcache命中率太低,程序需要读取memcache的同时又要读取一次数据库

3、像判断黑名单这种情况,如果backlist表不超过1M,则可以调用get_rows_cache()把整张backlist表都读进memcache里。以后判断用户是否处于黑名单的时候可以读取memcache里面的backlist表,然后用简单的数组循环foreach()判断便可知道用户是否存在黑名单中。另外不要忘记了,每次添加或者接触黑名单用户的时候不要忘了调用delete_rows_cache()

4、利用第3点的思想,可以类推到很多地方。例如论坛发帖时的关键字过滤。可以把关键字都加载到memcache中再比较(同时,在代码中比较,cpu消耗不用云豆)

5、上面说了多条记录的缓存。忘记了单条记录的缓存。单条记录缓存get_row_cache()适合的情况很多。举几个例子。(1)读取公告。根据公告id和缓存公告内容。因为网站公告通常都是每个页面都读取的,所以读取进缓存最适合了。(2)、读取用户资料。用户进网站后,直接读取用户资料并放进缓存。

新窗口打开 关闭