wordpress缓存类WP_Object_Cache分析

wordpress的缓存类WP_Object_Cache在wp-includes/cache.php文件中。与一般的缓存类将数据缓存在文件中不同,WP将数据缓存在内存中,所以每次客户端请求,都要重新生成缓存,请求处理结束后,缓存就清空了。这样唯一的好处是,一次请求中,需要多次使用的数据,比如site_name,只需要去数据库中查询一次,以后直接读内存就可以了,速度比读数据库快,提高程序执行效率。
下面来分析WP_Object_Cache的实现

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
class WP_Object_Cache {

    //所有的缓存数据都保存在这个变量里
    var $cache = array ();

    //缓存中不存在的变量
    //调用get方法是取不到的值,都保存在这里
    var $non_existant_objects = array ();

    //记数 记录取值时成功的次数
    var $cache_hits = 0;

    //记数 记录取值时失败的次数
    var $cache_misses = 0;

    /**
     * 向缓存中添加新数据
     *
     * @使用 WP_Object_Cache::get 检查缓存中是否已存在该数据.
     * @使用 WP_Object_Cache::set 检查了缓存中数据不存在后,设置新值
     *
     * @参数 int|string $id 标识缓存中的数据
     * @参数 mixed $data 要保存的数据
     * @参数 string $group 缓存内容的分组 wp把数据按不同的类型分组,如comment、bookmark等
     * @参数 int $expire 缓存内容的过期时间 从未使用过
     * @返回值 bool 缓存ID和组存在时返回false,否则返回true
     */

    function add($id, $data, $group = 'default', $expire = '') {
        if (empty ($group))
            $group = 'default';
        //如果组$group下id为$id的值已经存在,则不能新增,返回false
        if (false !== $this->get($id, $group, false))
            return false;

        return $this->set($id, $data, $group, $expire);
    }
        /**
     * 删除组中特定缓存ID的数据
     *
     * 如果缓存ID不存在并且$force=false时,什么也不会发生,$force默认为false.
     *
     * 成功的时候$non_existant_objects中会保存该ID,表示这个缓存数据不存在.
     *
     * @参数 int|string $id 标识缓存中的数据
     * @参数 string $group 缓存的分组
     * @参数 bool $force Optional. 是否强制删除组中的缓存ID
     * @返回值 bool 没有删除时返回false,删除成功时返回true.
     */

    function delete($id, $group = 'default', $force = false) {
        if (empty ($group))
            $group = 'default';

        if (!$force && false === $this->get($id, $group, false))
            return false;

        unset ($this->cache[$group][$id]);
        $this->non_existant_objects[$group][$id] = true;
        return true;
    }

    /**
     * 清空所有缓存数据
     *
     * @返回值 bool 永远返回true
     */

    function flush() {
        $this->cache = array ();

        return true;
    }

    /**
     * 取得存在的缓存数据
     *
     * 根据ID和分组搜索数据,如果数据存在,返回数据     
     *
     * 失败时检查$non_existant_objects属性,如果缓存ID和分组在这个属性中存在,直接返回.
     * 如果不存在,则cache_misses加1,并把ID和分组添加到$non_existant_objects中。
     *
     *
     * @参数 int|string $id 标识缓存中的数据
     * @参数 string $group 缓存所在的分组
     * @返回值 bool|mixed 失败时返回false,成功时返回ID对应的数据
     */

    function get($id, $group = 'default') {
        if (empty ($group))
            $group = 'default';

        if (isset ($this->cache[$group][$id])) {
            $this->cache_hits += 1;
            if ( is_object($this->cache[$group][$id]) )
                return wp_clone($this->cache[$group][$id]);
            else
                return $this->cache[$group][$id];
        }

        if ( isset ($this->non_existant_objects[$group][$id]) )
            return false;

        $this->non_existant_objects[$group][$id] = true;
        $this->cache_misses += 1;
        return false;
    }

    /**
     * 替换已经存在的数据
     *
     * @see WP_Object_Cache::set()
     *
     * @参数 int|string $id 标识缓存中的数据
     * @参数 mixed $data 要保存的数据
     * @参数 string $group 缓存分组
     * @参数 int $expire 缓存过期时间
     * @返回值 bool 不存在时返回false,替换成功时返回true
     */

    function replace($id, $data, $group = 'default', $expire = '') {
        if (empty ($group))
            $group = 'default';

        if (false === $this->get($id, $group, false))
            return false;

        return $this->set($id, $data, $group, $expire);
    }

    /**
     * 把数据保存在缓存中
     *
     * 缓存数据按照$group进行分组. 不同组中可以添加相同ID的数据.
     *
     * $expire参数没有使用,因为php页面执行结束时,缓存会自动结束. 一般在使用文件来缓存数据的插件中使用。
     *
     * @参数 int|string $id 标识缓存中的数据
     * @参数 mixed $data The 要保存的数据
     * @参数 string $group 数据所在的分组
     * @参数 int $expire 过期时间,未使用
     * @返回值 bool 永远返回true
     */

    function set($id, $data, $group = 'default', $expire = '') {
        if (empty ($group))
            $group = 'default';

        if (NULL === $data)
            $data = '';

        if ( is_object($data) )
            $data = wp_clone($data);

        //保存值到全局变量中
        $this->cache[$group][$id] = $data;

        //如果这个选项在non_existant_objects中存在,则取消存在
        if(isset($this->non_existant_objects[$group][$id]))
            unset ($this->non_existant_objects[$group][$id]);

        return true;
    }

         /**
     * 显示缓存状态
     *
     * 显示缓存取值成功、失败的次数和所有的缓存分组及组下的数据
     *
     */

    function stats() {
        echo "<p>";
        echo "<strong>Cache Hits:</strong> {$this->cache_hits}<br />";
        echo "<strong>Cache Misses:</strong> {$this->cache_misses}<br />";
        echo "</p>";

        foreach ($this->cache as $group => $cache) {
            echo "<p>";
            echo "<strong>Group:</strong> $group<br />";
            echo "<strong>Cache:</strong>";
            echo "<pre>";
            print_r($cache);
            echo "</pre>";
        }
    }

    /**
     * PHP4风格的构造函数; 调用PHP 5风格的构造函数

     * @返回值 WP_Object_Cache
     */

    function WP_Object_Cache() {
        return $this->__construct();
    }

    /**
     * Sets up object properties; PHP 5 style constructor
     *
     * @since 2.0.8
     * @返回值 null|WP_Object_Cache If cache is disabled, returns null.
     */

    function __construct() {
        /**
         * @todo This should be moved to the PHP4 style constructor, PHP5
         * already calls __destruct()
         */

        //注册一个结束时的回调函数
        register_shutdown_function(array(&$this, "__destruct"));
    }

    /**
     * 析构函数  *
     * Called upon object destruction, which should be when PHP ends
     *
     * @返回值 bool True value. Won't be used by PHP
     */

    function __destruct() {
        return true;
    }

}

总体分析,wp的缓存类,实现了数据库一样的增删改查功能。只不过数据是保存在内存里,而不是数据库中。

wp中调用缓存对象的方法是并不是直接在代码中像这样调用

1
2
3
    global $wp_object_cache;

    return $wp_object_cache->add($key, $data, $flag, $expire);

而是封装在一个方法里:

1
2
3
4
5
function wp_cache_add($key, $data, $flag = '', $expire = 0) {
    global $wp_object_cache;

    return $wp_object_cache->add($key, $data, $flag, $expire);
}

调用的时候,像这样调用:

1
wp_cache_add($comment->comment_ID, $comment, 'comment');

由原来的两层结构,中间又加一层封装,变成三层,提高了代码的重用性、扩展性和可维护性。这正是我们写程序时应该追求的。

wordpress缓存类WP_Object_Cache分析》上有6条评论

  1. excing

    Cache类在wp-includes/cache.php文件中,其中析构函数__destruct,注释中是说:

    在对象销毁之前,保存对象缓存。

    而不是你说的:

    每次客户端请求,都要重新生成缓存,请求处理结束后,缓存就清空了。

    代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        /**
         * Will save the object cache before object is completely destroyed.
         *
         * Called upon object destruction, which should be when PHP ends.
         *
         * @since  2.0.8
         *
         * @return bool True value. Won't be used by PHP
         */
        function __destruct() {
            return true;
        }

    wp是将每个用户的每次请求都缓存在内存中,以提高下次访问的速度。
    不知道我的理解对不对?

    回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注