原理:

  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)
    }