论坛首页 综合技术论坛

memcache遍历策略

浏览 5822 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2012-11-08   最后修改:2012-11-08
mysql的内存引擎其实很好用,但是我担心并发大还是不行。

用memcache,不好遍历。我想了一个办法。

键分三种,

第1种,只有一个就是news_index_index,值的模样是逗号分隔的字符串或数组。
第2种,news_index_XXX,XXX是数字,长度不限,如果xxx=1200,则news_index_1200只能存 120000-120099的新闻id,值的模样同上。
第3 种,news_XXX,XXX长度不限,就是新闻id,值就是点击量,int型

分3步,存,取,遍历(倍数为100)。


假设有一个item,key为news_index_index,值为如同1,2,4,44,这样的数据。

当一篇新闻的id例如12004,则除以100取整,得到120,
查询key=news_index_index
if (没有120) {
  在key=news_index_index的item 的值中添加120;
  添加news_index_120的item ,值为空。
}
查询key=news_index_120,查有无12004

if (有12004) {
   key为news_12004   的item 的值加1;
}else {
  key=news_index_120,的item的值加上一个12004;
  添加一个item,key=news_12004,value=1
}


如果要id为333367的点击量,则直接取key为 news_333367的item的值即可

遍历
当我要遍历所有在 memcache中的新闻id时,则有了上述机制后,太简单了,就不说了。

备注
另外,为防止数据过多,可以在半夜把点击量保存到数据库中,然后清除第2、3种键,并把第一个键的值清空。
   发表时间:2012-11-08  
谨受教……………………………………
0 请登录后投票
   发表时间:2012-11-08  
上php代码
<?php

/**
 * 新闻点击量memcache使用
 * $mem = Sys::get_memcache();是获得memcache对象的
 * 建议每晚把流量加到表中,或每隔1小时等,然后每晚清除
 * 实际应用中缓存应该是稀疏的,除非被搜索引擎遍历等,关系也不大。
 * 
 * @author: 
 */
class Dao_NewsClick
{
    //取某id的流量
    public function load($id, $type='news') 
    {
        $id = intval($id);
        $mem = Sys::get_memcache();
        $key = "{$type}_{$id}" ;
        $result = $mem->get($key);
        if ($result === false) {
            return null;
        }else {
            return $result;
        }
        
    }
    
    /**
     * id的流量加1
     */
    public function save($husheng_id, $type='news')
    {
        $rate = 100; //倍率
        $key1 = "{$type}_index_index"; //总索引的键
        $mem = Sys::get_memcache();
        $id = intval($husheng_id);
        $index = intval( $id / $rate ); //索引
        $key2 = "{$type}_index_{$index}";
        $key3 = "{$type}_{$id}";
        
        //先查总索引;
        $index_index = (array)$mem->get($key1);
        if ($index_index === false) {
            //如果没有,要先生成
            $mem->set($key1, array(), 0, 0); //存个数组进去
            $index_index = (array)$mem->get($key1);
        }
        if (!in_array($index, $index_index)) {
            $index_index[] = $index;
            $mem->set($key1, $index_index,0,0); //保存到总索引
            $mem->set($key2, array());
        }
        //查具体的桶
        $barrel = (array)$mem->get($key2);
        if (!in_array($id, $barrel)) {
            $barrel[] = $id;
            $mem->set($key2, $barrel,0,0);
            $mem->set($key3,1,0,0);
        }else {
            $mem->increment($key3);
        }
    }
    
    /**
     * 打印所有成html,调试用
     */
    public function print_html($type="news")
    {
        echo "<ul>";
        $key1 = "{$type}_index_index"; //总索引的键
        $mem = Sys::get_memcache();
        $index_index = (array)$mem->get($key1);
        foreach ($index_index as $value) {
            $key2 = "{$type}_index_{$value}";
            $barrel = (array)$mem->get($key2);
            foreach ($barrel as $v2) {
                $key3 = "{$type}_{$v2}";
                $v3 = $mem->get($key3);
                echo "<li>{$v2}:{$v3}</li>";
            }
        }
        echo "</ul>";
    }
    
    /**
     * 清除所有键,只留一个总的空的。
     */
    public function clear_all($type="news")
    {
        $key1 = "{$type}_index_index"; //总索引的键
        $mem = Sys::get_memcache();
        $index_index = (array)$mem->get($key1);
        
        foreach ($index_index as $value) {
            $key2 = "{$type}_index_{$value}";
            $barrel = (array)$mem->get($key2);
            foreach ($barrel as $v2) {
                $key3 = "{$type}_{$v2}";
                $mem->delete($key3);
            }
            $mem->delete($key2);
        }
        $mem->set($key1, array(),0,0);
    }
}
0 请登录后投票
   发表时间:2012-11-12  
唉唉,请说详细点嘛,这样看起来很乱的了
0 请登录后投票
   发表时间:2012-11-12  
如果是遍历,还不如直接访问数据的。
0 请登录后投票
   发表时间:2012-11-12  
你可以用redis
0 请登录后投票
   发表时间:2012-11-13  
memcache做你这个太煎熬了,推荐redis,我们公司的使用redis,每几分钟把点击数更新到数据库中去
0 请登录后投票
论坛首页 综合技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics