国外设计欣赏网站 - DOOOOR.com

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,微信登陆

搜索

[Drupal优化/SEO/环境] Drupal教程:自定义缓存之共享内存

[复制链接]
发表于 2-7-2012 02:39 | 显示全部楼层 |阅读模式

对于高性能、高并发软件架构中一个重要的优化策略就是,能在内存中处理的决不能放到外存中。这里外存包括:网络I/O,DB,硬盘。
对于一个Drupal站点,我们都要使用到缓存,前文《drupal性能优化经验贴》中也谈到,必须使用cache。
一般情况下,我们使用memcache,大型站点,使用分布式memcache,并且memcache常常和Application不在同一台服务器上面。这就会带来一个问题,内部网络IO。对于小站点可能没有什么问题,但是对于一个大型站点,这个问题很严重。
因为Drupal的某些缓存比较大,比如theme-registry, content-type-info, locale翻译信息,对于一个较复杂的站点,这几个缓存加起来至少1M以上,大到3-5M。如果一个request需要3M的缓存,那么1000request需要3G的流量,这样即便是内网的IO,也会造成很大的瓶颈。(笔者曾经就遇到这样的问题,所以这里就是对这个问题的解决方案的分享)。

如何解决呢,就是将某些缓存,再缓存到本机,这样就会省去网络IO,降低了网络瓶颈。
缓存到本机,我们可以使用本机文件缓存,比如缓存到tmp下面。但是按照我们的原则: 能在内存中处理的决不能放到外存中,我们可以把这缓存放到内存中(前提是硬件服务器内存比较大,现在一般较好的服务器可以达到8G,以至于20,30G,这样内存完全可以拿出1G去缓存这些内容)。

为了方便,我们可以写一个接口函数,去封装缓存动作,可以缓存到APC(内存共享)、文件。这里我们重点选择文件夹,因为文件夹正常是缓存在磁盘上,但是我们可以把这个文件夹挂载到内存上。如果内存不够可以取消内存挂载,这样操作起来比较灵活,也不需要修改任何代码。

200
2 H; @, I& v5 h201' U& P. F) i( i: L3 S
202
6 j8 s; X  E' |+ w- C- i203
" K0 G7 i# u. j8 C204
4 w: Q, P$ _9 G; h7 a205
$ b3 ?3 Z8 s3 E5 e5 v8 }206& A+ I9 @5 K' z# p
207
8 M  b" c+ X; ~  [. k& N208
, F; k# Q0 y0 X/ x2090 _+ i% x, V. \) ?/ e( Q8 Q
210" P% p' z/ I  }
211
2 @& E  T/ K  w# g: y212
9 n; R4 V, f) ^, b$ Z213& |4 @3 v. J0 ~9 P; n& o
2148 S& ~+ B5 N5 B7 _: E" z/ M
215
4 W2 o1 R, p! i3 I216
( c. @8 u3 t5 @0 o  D. ]  R217
! n, [) N+ }5 X9 y2184 A7 q/ J9 V7 {( i. P
219/ Z. d, P3 C% W( d9 V2 `' Y' }5 [
220/ b' Y( f7 F! B' n* B
221
; |1 K) q1 L+ K* ]/ s% b2 J222& U1 g2 K  Z" n$ G% W# `0 V
223% q: ~7 g6 u* C- ]1 T4 g
224
$ ]: \( V- c( p8 Y5 T; r4 |225" n1 ?9 O" x9 R% [# r' j' d# f  n
226
" H/ v/ X2 v, Q: c227
/ S! c- `; ?1 X0 F/ h) x0 R228. }0 }: F, q, O! }" t1 I
2299 p5 |, _1 \5 {4 T+ P
230# e: G2 l) B/ S( B
231
4 }. H' q1 S' j) P% t3 r8 Z232
* X6 F3 T0 E# V+ p. @233
& W& @1 o. v) I8 E234& ?! @  C1 p" d+ I5 e. |* Q
2352 t% i# `% I. F
236& m+ y* f6 ]* W6 H
237
8 V: q, c2 ]. w# b6 @9 ]9 z238, D$ S* B; x9 {  u# c: {+ K. _
239
" |6 C- p! c' @/ D" m240
* q0 V/ u0 v6 h& @2413 m, i9 l, B7 o* [* i7 o
242
' t$ m8 e/ y+ H( {* @; i' B243
0 i/ \& q) A% z6 U; n' H/ d244
4 P, V, E- [/ P' P6 B, Q245
2 ^/ D) F) e: ]: |0 b: G% h2469 H  s; [2 V0 v7 h$ I  W
247
* v# ~# o" Z# C/ p+ o* N248
( D5 ?) ]. v) W' i  Q3 W249
# J: C7 `# h3 j) i( U2505 k/ @# d7 V0 z8 x7 H# s. k0 e" f' p
251+ T- O# y8 P9 _: ?" O
252) Z0 S8 S: \' ?' g& R
253
% b9 U/ G2 x! G' q) G/ Q0 f2543 L# W1 L, L4 p+ p7 v
255
7 ?/ D8 ?" Q! ]256/ H4 N% D( q. ^* c
257
3 C& X8 V) \: i& U$ t1 e8 x! e258
! d, f9 {' S6 d259
; D- _5 p, X5 v5 `) E7 y' k2 o260
' R- P" G8 ?9 V7 Z# u2610 _6 c0 g& k$ |: P( q! L( g
262- z: C3 v) A* m8 e3 _# e
263
9 @; B- v+ s! @! a) |* h) L2640 n! }& N+ V0 F' V
2651 B5 ]  s+ [9 p3 _  Y7 q: r2 ?
266; z, c. O4 y2 V7 q7 t
267
- l  L, @# d& b/ Y2 w3 f268
7 L2 D/ |! q  I7 \; L- @269- m5 J6 q6 F- ~. s6 i4 z: E. L/ A6 Y
270
1 t/ G6 I4 Y6 O. V9 _# U271
0 y! L9 t% i$ u272
0 T' I, I1 r$ f+ v. Q+ h273$ b8 R% g6 [  l' K! L; K' ~# g& d
274
: Y& O7 ~$ v2 L* k' @& x275
3 ?7 N9 ]/ Q7 a2 ]$ h$ j  ]0 i276
/ N# a1 H2 ^" T277
6 E$ ~- k; V8 n8 K) q+ K5 W278! F5 L) T# ~% W8 \" d, q
279
9 ?. A' y9 L' N+ p1 M7 `8 ~4 i0 ]280# x2 B8 P( _1 B4 ]' u2 ?3 B) n' b
281
3 ~! I' G3 e3 Y' w( L282
  P1 f+ t6 z9 |8 q9 h1 M. `$ |% W0 h7 \2838 B! b5 v# j9 n- Q
284- X% J& g6 O* w' F4 C# K0 v
285
. x$ H/ Q7 l  l7 e( C1 z/ ~  I2863 j8 X* q6 [3 Z6 \' A
287
4 \7 f% A3 ^" i) b, P: Q1 h2 o! s288
& `& m  E6 j! J289/ n+ M# u  T1 N$ m
2907 A8 N' [+ d9 k- |! j, Q+ L3 w
2910 {* K0 ~  d: F' D* F
292/ j, a$ v5 P. B7 k  |% y8 Q, ]0 j
293
8 }$ s/ V' A1 `0 H4 d# B: f8 C7 s294
3 p7 c! k+ E0 M295" Q) A/ [+ [9 K( C* G. F
296) L7 C& U8 B2 {" U: n! r
297$ p- v8 X, D! V
298
3 d4 s& r/ H8 p4 t* P* g) a! z9 G299$ z% r  _- h1 Z/ X3 p. q; Y1 M
3003 Z0 v- I& d% N1 k; i
301# z' I0 l5 j" [& W* }$ g
302+ a# i4 ^& Y- D* E
303  G5 x0 j0 d8 U' q
define('V_CACHE_FILE', 1);
2 a2 X# z: ]: ~* j" E. j 
# n4 e& p! ]$ l$ R* c/**
* Z% a- V; K5 B% @8 z *@important Create the cache folder to store the cache data firstly& i+ a$ k9 [" q9 T/ v0 M
 : w- Q) w  A9 z9 Z2 P+ D" ~" N1 O
   #create memcache local cache folder
3 A4 v) e' o9 r   mkdir memcache ; sudo chown nginx:nginx memcache4 \* f' M8 {: G2 x
 * S1 V& B/ y. I
 */
' `' y  m% J3 Ifunction v_cache_file_dir() {
' v- e" k6 k3 L* t4 K  $path = dirname($_SERVER['SCRIPT_FILENAME']);
% s' x' O% f1 W) W! o  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';1 M, D! V' i' b4 x+ k& |/ r9 Z9 T
  $dir  = rtrim($path, '/') .'/memcache';
& z. I$ F& ]# s- W6 f! m; S 
' h! b1 S# b3 c7 K" F( {# ~  if($_GET['debug'] == 'test-cache') {
" ]) `4 ~% s% [: {' J+ d8 D    drupal_set_message($dir. '@DIR');  {1 k9 s# J: [4 K
  }. S$ F1 l8 R6 _- T* y( }! B) N
  if(!is_dir($dir)) {* @9 l8 Z4 @- M/ Q' f$ `7 Z
    #mkdir($dir);+ c1 X% V2 Q* K$ P/ U$ f. y
    throw new Exception('Create local directory for cache, ' .$dir);
& Q% q6 Q9 b! Z4 B+ Q1 U  }
/ Z, Z0 B/ b3 L+ _' k! [: J% E  return $dir;7 j# K/ P% u: g' Z3 T- A) a
}3 o* u( X: h7 S2 r' X! y
 ) R( }8 Z0 f) R: z6 i
function v_cache_file_set($key, $value) {( }0 L; ]5 {0 R1 d5 v8 Z
  $dir = v_cache_file_dir();- t4 C, O5 u( A3 w! K! Y2 Q) }$ I& O
  $file = "$key.ser";
# A$ o' R% O3 B" U% q9 r$ x  if($_GET['debug'] == 'test-cache') {% F3 t/ l, Z2 c/ \5 f
    drupal_set_message($key. '@FILE_CACHE_SET');
4 W+ g& \7 d7 q  }% s' L# `1 l# l! e. Q
  file_put_contents($dir .'/'. $file, serialize($value));
; l- S4 q* _4 w9 K}. w: b- ^9 C" S* y7 u
 
) w0 O8 G- j* \+ o; D8 cfunction v_cache_file_get($key) {8 g( x7 e8 l! c$ C+ c! V+ X
  $dir = v_cache_file_dir();
& U" B+ G0 d( H ' E) G  f% \3 J) Z8 V$ [
  $file = "$key.ser";
, F+ J% @' c; A& {8 ~7 ?& W/ m' W" i  $file = $dir .'/'. $file;
3 |7 w4 q( \" c, T/ z  if(file_exists($file)) {
/ _+ f7 G3 h! R, T3 k2 r" Y8 J& R     if($_GET['debug'] == 'test-cache') {; g2 F1 z' j' O
      drupal_set_message($key.'@FILE_CACHE_GET');
8 l4 |7 G: L# W; _% ^     }
( V9 a( R6 W0 d    return unserialize(file_get_contents($file));
) W# S# {7 k0 W5 t  }% u' H& e. i- s2 u/ b: E: {
  else {8 P7 U/ z( i1 R# I7 v1 `+ a
    return false;/ j7 c+ S( g; ?# W2 [' l$ `" s
  }, a" x9 p" T4 H4 `* S( m6 ^
}. o0 o9 B2 u( N; @' h
 $ ]. c) l9 {9 i/ R8 g
function v_cache_encode_key($key) {  b4 B& T$ ~: S% {
  $address = $_SERVER['SERVER_ADDR'];
: {8 f! g' ^. Y  //$key     = str_ireplace(':', '-', $key);
+ t7 v4 W! t0 m! p8 ~2 _8 t  $key = "$key:$address";
, q' o( D6 z) H  T7 p  return $key;
5 J3 G$ m) F$ d$ M- v8 U}' e. r$ A4 i: q5 g+ F0 j
 9 }! @# t1 d7 e+ r
function v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {
, Y5 Y1 s+ c! {5 m$ ~( D9 {  $key_mem = v_cache_encode_key($key);! a3 w. n* Y' X: x
  if (function_exists('apc_cache_info')) {& z0 y% J( Q3 B  e7 R& N+ d
    apc_store($key, $value, 60*60);//1 hour( T4 L  d* ^7 m3 ]# }, X
    cache_set($key_mem, time(), $table, $expire);
& l) V- m+ p& y2 t) l  }# N5 ], x5 V3 p( w
  else if (V_CACHE_FILE) {5 j. P0 w: y" ?3 W! A% z+ ?
    v_cache_file_set($key, $value);//1 hour
. p) m  u0 l# a2 a    cache_set($key_mem, time(), $table, $expire);- Q$ G. P  A& N5 ^- N( W
  }
- o9 K2 p+ P/ I5 J7 h) j  else {) Q  x! @' m$ J- w
    cache_set($key, $value, $table, $expire);
8 |) m& n) r" b( [8 [2 |8 V, e1 U  }
4 f! A$ n9 G9 K) v9 a) v& _}3 x+ S" H1 y& c! ]% h) `
 
5 L. e, n0 W" l+ s$ afunction v_cache_get($key, $table = 'cache') {( B$ a) l' U6 Y0 p- _( Y! _1 H8 p
  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {
/ `% D0 A9 d* w0 b7 i    static $static;' M9 K7 v3 k9 J( k: h
    $ret = false;2 I/ Y: E7 d8 T2 b0 O; E" E
  if (isset($static[$key])) {+ M, m4 F4 {( Q1 Z& }7 l0 X
    $ret = $static[$key];
4 e5 r  M2 W% F9 p8 d  }
6 z% x' b! j2 R4 m+ z; r: p3 c  else {
( y  i* e6 {7 ], a; _  b8 r  p5 C   $key_mem   = via_cache_encode_key($key);
4 r$ Y4 m! n7 Z   if(cache_get($key_mem, $table)) {
& L: O2 E4 a" t$ z9 W/ U, F' a     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';, K6 Z" T% c8 b5 v; L
     $value = $cache_callback($key);6 |3 g' U8 [9 @1 I
     if($value) {
8 P( t3 p4 _9 s% I5 Z. M       $cache = new stdClass;3 z. Z& s5 v3 @! D: x1 ?; Q+ ?
       $cache->data = $value;7 J7 v: I' M" W. l
       $static[$key] = $cache;
1 \" \# Q8 i' i1 J6 _  g9 b       $ret = $cache;
9 `7 [4 D& K" J     }
- `% L! z5 ~% s* n  D; Z   }2 @- d7 ]# Q3 S& @$ ]
  }
- F8 @# a7 g8 m: B. A  return $ret;
' e, ^1 b( G5 g }
5 `" g) b# v7 {, b7 p8 Y else {
+ K* ?" i9 n0 Y  {9 C* V9 x% E5 _   return cache_get($key, $table);3 r) M" V! t; \& p9 Q9 i
  }# w/ v! X" G7 B
}
& F) ^0 f: ^. d% \ 
% }- E& q6 ]6 afunction v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {  E# {8 f1 H* W1 E/ W! \8 w
  if ($cid) {
5 W2 m7 ?# `& J: \' c- l( y    cache_clear_all($cid, 'cache', TRUE);, b8 r( a- W( j) h
    //apc_clear_cache('user');8 d5 h  P- N; {4 r
  }3 e4 C% Z8 j4 @1 D
}

添加了上面到代码之后,我们需要修改一些drupal核心code,去调用我们自己定义的cache方法,重点关注下面几个cache:

  • common.inc 里面的shema,函数: drupal_get_schema里面调用的cache方法。
  • theme.inc 里面的theme-registry,函数:_theme_save_registry。
  • locale.module里面的locale函数,修改里面的cache方法。
  • content.module里面的content-type-info, 函数:_content_type_info。

因为以上信息缓存一次,修改机会比较小,所以缓存到本机是比较理想的做法。
还有一个需要注意的,上面的缓存虽然存到的本机,但是cache的key还是存到了drupal正常的cache里面,所以当清除drupal的cache之后,这些key消失,通过这样的方法,可以实现对cache清除的操作控制。

当然,除了修改缓存的操作,还需要一个清除缓存的操作,我们可以通过实现相关hook来操作。
这个修改是需要修改drupal核心代码的,所以请谨慎使用。

Drupal自定义cache操作流程


声明: 本站所有文章欢迎转载,所有文章未说明,均属于原创,转载均请注明出处。 
本文有效链接: http://www.drupal001.com/2011/10/drupal-custom-cache-tips/ 
版权所有: Drupal与高性能网站架构 http://www.drupal001.com



|2011-2026-版权声明|平台(网站)公约|DOOOOR 设计网 ( 吉ICP备2022003869号 )

GMT+8, 3-20-2025 05:47 , Processed in 0.295288 second(s), 108 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表