Tag Archives: memcached

使用memcached做数据库点击数统计缓冲

原理:

  1. 先从数据库读取最新的点击数,更新到缓存中。
  2. 点击动作产生时,在缓冲做自增操作。
  3. 把被点击的ID写入缓存中,以表名为组。表明缓存中有该ID的点击数,需要进行入库操作。
  4. 定时更新缓存数据到数据库。
  5. 如发现入库周期内,点击数无更新,则放弃入库,并山删除表名组中的ID。

且看代码:

   
    /**
     * 更新点击数
     *
     * @param string $table
     * @param int $id
     */
    function click($table, $id) {
        $config = ZFactory::getConfig();
        $key_prefix = $config[‘click’][‘key_prefix’];
        $cache = ZFactory::getCache();
        $key = $key_prefix . ‘_’ . $table . ‘_’ . $id; // 点击数键
        $click = $cache->get($key); // 获取点击数
        if (!$click) {
            // read from table
            $id = intval($id);
            $db = ZFactory::getDb();
            $table = $db->escape_string($table);
            $sql = "SELECT click_count FROM `log_clicked` WHERE click_id=’$id’ AND click_type=’$table’";
            $db->query($sql);
            $result = $db->fetch_object();
            $click = $result ? $result->click_count : 0;
            $cache->set($key, $click);
            
            // 维护一个ID列表
            $list_key = $key_prefix . ‘_’ . $table; // 列表键
            $list = $cache->get($list_key);    // 获取列表
            if (!$list) $list = array($id);
            else $list[] = $id;
            $cache->set($list_key, $list);
        }
        return $cache->increment($key);
    }
    
    /**
     * 把缓存中的数据持久化到数据库
     *
     */
    function click2db() {
        $config = ZFactory::getConfig();
        $key_prefix = $config[‘click’][‘key_prefix’];
        $tables = $config[‘click’][‘tables’];
        $cache = ZFactory::getCache();
        foreach ($tables as $table) {
            $ids_key = $key_prefix . ‘_’ . $table;
            $ids = $cache->get($ids_key);
            if (count($ids))
            foreach ($ids as $k=>$id) {
                $id = intval($id);
                // 缓存内的点击数
                $key = $key_prefix . ‘_’ . $table . ‘_’ . $id;
                $click = $cache->get($key);
                // 读取数据库里的点击数
                $db = ZFactory::getDb();
                $table = $db->escape_string($table);
                $sql = "SELECT click_count FROM `log_clicked` WHERE click_id=’$id’ AND click_type=’$table’";
                $db->query($sql);
                $result = $db->fetch_object();
                $dbclick = $result ? $result->click_count : 0;
                // 如果周期内没有人点击
                if ($dbclick > $click) {
                    // 从缓存中摘除该ID
                    unset($ids[$k]);
                } else {
                    // 把点击数写入数据库
                    $sql = "UPDATE `log_clicked` SET click_count=’$click’ WHERE click_id=’$id’ AND click_type=’$table’";
                    $db->query($sql);
                }
            }    // foreach ($ids as $k=>$id)
            // 把ID列表写回缓存中
            $cache->set($ids_key, $ids);
        }    // foreach ($tables as $table)
    }
   
 

用telnet测试memcached服务器

检查telnet程序是否可用:which telnet

如果没有安装,则安装之:aptitude install telnet

开始测试:

dev-server:~# telnet 192.168.0.240 11211
Trying 192.168.0.240…
Connected to 192.168.0.240.
Escape character is ‘^]’.
set key1 0 60 9
seaprince
STORED
get key1
VALUE key1 0 9
seaprince
END
stats
STAT pid 2557
STAT uptime 249422
STAT time 1246175982
STAT version 1.2.2
STAT pointer_size 32
STAT rusage_user 0.008000
STAT rusage_system 0.004000
STAT curr_items 2
STAT total_items 24
STAT bytes 121
STAT curr_connections 1
STAT total_connections 30
STAT connection_structures 2
STAT cmd_get 26
STAT cmd_set 24
STAT get_hits 21
STAT get_misses 5
STAT evictions 0
STAT bytes_read 3021
STAT bytes_written 2886
STAT limit_maxbytes 67108864
STAT threads 1
END
quit
Connection closed by foreign host.
dev-server:~#

整数操作:

dev-server:~# telnet 192.168.0.240 11211
Trying 192.168.0.240…
Connected to 192.168.0.240.
Escape character is ‘^]’.
get key1
END
set key1 0 3600 3 123
123
STORED
incr key1 5
128
decr key1 5
123
delete key1
DELETED
get key1
END
quit
Connection closed by foreign host.
dev-server:~#

高亮的是需要输入的命令。跟随的是返回。

参考:http://lists.danga.com/pipermail/memcached/2005-April/001332.html

 

php中的memcached扩展使用

本文提供php_memcache.dll 扩展下载,本版本适用于绝大多数PHP 5版本,已经测试5.2.6, 5.2.9-2,欢迎您把测试结果分享出来。

另外,提一下用memcache做session.save_handler的方法。

            ini_set(‘session.save_handler’, ‘memcache’);
            ini_set(‘session.save_path’, ‘tcp://192.168.0.240:11211’);

以下用正常的方式使用session,呵呵,简单吧!如果有更多的服务器,用逗号分隔即可。

            ini_set(‘session.save_path’, ‘tcp://192.168.0.240:11211,tcp://192.168.0.241:11211’);

还可以带上参数,这些参数和Memcache::addServer()保持一致:

            ini_set(‘session.save_path’, ‘tcp://192.168.0.240:11211?persistent=1&weight=1&timeout=1&retry_interval=15’);

更新:

还可以把tcp换成udp,以得到更好的效率,更低的资源消耗:

            ini_set(‘session.save_path’, ‘udp://192.168.0.240:11211,tcp://192.168.0.241:11211’);

debian下memcached的安装与使用

下载并安装memcached:

aptitude install memcached

安装成功后,本机可以正常连接,但局域网内依然不行。后发现是配置文件的问题:

vim /etc/memcached.conf

将-l 127.0.0.1的一行注释掉。因为这一行说明了只监听本地的11211端口,局域网当然无法连接。

然后重启memcached:

/etc/init.d/memcached restart

成功!

另附memcached简单测试方法和控制命令:

telnet 192.168.0.240 11211     测试连接是否正常

/etc/init.d/memcached start  启动    同理,restart 重新启动,stop是停止。