国外设计欣赏网站 - 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
5 u! N% R) h4 ~' d201- K3 I0 V- ]; k% X
2028 G1 r& K* b' x
203
+ e7 _" u9 i0 ^2 @) G6 t: ?% f9 p204
" A6 y& V% N# E) ^; k2 W$ d2053 K  W/ q6 z+ y8 b
2062 a* R$ e# g5 X; Z/ G4 y
207
- K: i0 |% r- A208
2 m; n7 |# O$ w: Q209+ U* ?' J- l' L2 s7 Y- {
2101 {$ t1 i  A) ~- J! j: l+ E
211
8 ~# Z) `/ i, ^212
6 Q4 p$ t$ k* ^+ G  t213' `1 t4 j7 b; N) N/ h8 k
2148 c: S5 Y6 d5 t. Y: j
215
0 q6 J$ r. G  ]* }( \/ i216: M# B8 _9 k  R5 }2 d5 K; Y
217- p- ~' z' t- m  f9 z9 C8 W. i
218. B- g5 A  A+ O- e; I9 l6 ^+ e
219
* K) d( g0 L8 y220
& J1 r1 I" o% D+ d  z221, O% W9 m4 N! o: X! n" [. K3 K
222
" j2 Q0 v9 i% O9 I! S$ Y0 b2 u223
9 q$ D* d3 E5 ?1 P224/ N, c6 G; k+ Y
225
* ]* u( s: L4 K& G( l* b226% F6 h7 Y. N0 V/ d
227
/ |6 Z  j; M$ c6 ~# D! ^" a" J228
6 y, z3 \- `9 z! a9 R229
) }7 m" l# q& u3 }# W5 A230
( N( A1 A3 U* J$ X6 c. P231
$ X1 \* J( W1 S# ^9 X6 m232
& s$ y* q' ]7 ?" J233  Q+ d; t  T( N7 \/ F0 ?) i
234
* k: A2 ]5 n% o# ?, ]235
) I/ ^: z/ _; ^/ n2 _2361 F# s* b2 J( N3 o
237
5 f5 N6 q/ F, {5 y1 f238! K9 K$ h3 ?8 ^
239
  f! ?8 f' W( |- e/ M5 C6 E240
; V9 L, V9 }& j6 \. J1 n' E8 w241
2 e. n6 }4 s# j: _: J9 h242* K, S/ J  a1 p1 d( L2 I( E8 D
243
' X* @2 u' J+ a1 B1 n7 @* a244! @) w9 W5 m6 x5 ]' H: {
245# x' N* t9 z' C
246
  u* _9 ]' v) ~* y0 }2471 W4 \6 D) x% N! y# G
248' I8 ^3 N6 `. ]
2496 p; d6 F1 k) a$ @# Z6 x: ^0 K
2509 s! |  t5 b/ l1 W. q1 q8 \4 f
251( D0 T+ w' X; x+ D# O6 B  [: G, }
252* S% J) E, _6 L  @% _
253* D, _7 t. \; k% s' M$ Z
254
* F& v6 e9 G9 E7 o9 r2550 S4 l; x! v1 x: X
256
# K" _. q1 z% }257
; W! R5 A- Z0 P% v' P258
# ^; a- t& H8 L2591 y; l1 E3 z4 r* ^) ]
260
7 q. @/ e4 b, B! C, b5 I$ ?261- p; I0 L' z, G
262; X: c5 Z' {& D6 {
263
# u8 S7 @7 b5 m- \264
) x7 }7 b9 k. N( ]! [. G9 `; i2655 \( ?' A; R0 F
266; z7 G9 J' I0 i! ]* x/ t9 x
267( Z; ^% ~5 h, i3 T  S5 G
268
. \/ L6 {+ b7 g; R& w5 {269$ u: v/ t) ^9 {% A
270' q$ f0 _. q$ o/ u/ l) a
2716 `% e5 b& Z, f" @& E  t1 l# H
2726 Y7 x# S2 A3 e5 V
273
7 Y; \' e4 g) y1 Z: n8 P/ E274
6 C7 y9 }8 @% w* V) k275, W+ _* H/ l- c5 U  D+ x- H
2761 J1 @1 ~2 w# o
2771 Y/ Q# o, ]8 t  `7 H
278, V1 @7 l5 B& l; x! ~
2796 |. S1 f* ^! T- W
280
. J0 v. W* c1 \) D5 {, s281
5 r, e) }2 b, e& y2826 q+ N' T; N) x- z1 {
283
: q0 P6 r% `2 H2 d4 t& _( v0 b284
) l% V- J- v* F3 r285  U- `8 z% z7 H) }- [# m
2862 X: v7 v3 s  `5 i
287: l/ u3 }- N6 t  a7 b  o& B9 w
288
% G" b# k4 O, M; {289; \* P' P* a" J. F$ Y- j4 Z
290
5 n8 Y2 a4 P3 Y, b" a1 p291
  I6 T' g. g) G4 L1 Z1 Z( I292
( ~/ d8 l3 H  T0 u! `293, C4 w) e2 [: j
2949 u5 o& L- y" v! a7 K7 t% p! w
2959 Z0 `( Y; v0 q; \4 C% ]! C1 [" Z
296) _+ c* i( a  Q
297
8 C4 v7 K. s3 o% P' d1 ~298
! i+ @; ?4 e! ?299
$ A4 ^0 f8 p2 G& |+ P300
4 n1 y. L9 \  Y8 a& @301; s5 n" G' ^6 p! a: g
302
; R( K) D8 m+ \, P2 O' Z8 Y! j- ]8 y/ C303; J  z& ]# \9 _* Z' e+ r
define('V_CACHE_FILE', 1);. ^5 R5 d' j2 |$ f  m9 y/ t) p' O$ e
 : o( [$ G4 B5 G4 Z# E
/**9 J' m* X7 p6 C5 `' N
 *@important Create the cache folder to store the cache data firstly
( {3 v" F" F2 J( w - S" ^' b7 w! O- z9 ]! h4 ]( Z3 p
   #create memcache local cache folder& N/ Q- T7 Q$ Y/ N
   mkdir memcache ; sudo chown nginx:nginx memcache
0 V9 [- s7 G( t2 _ + W3 ]4 O9 x% ?
 */
9 K- ?, @3 U- Nfunction v_cache_file_dir() {5 u/ b$ |& q/ f4 V1 j2 P: V1 b. [6 c
  $path = dirname($_SERVER['SCRIPT_FILENAME']);1 @% g* a9 v4 J3 x# g, a& ^6 `
  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';
  p8 B; f1 m2 L3 t  Y  V2 u. N  z  $dir  = rtrim($path, '/') .'/memcache';( u: J. W( q0 ]+ j, v
 ; k, h! A1 ?! f$ s& |- Q
  if($_GET['debug'] == 'test-cache') {
% Z7 u& T/ J! w0 H0 A5 T    drupal_set_message($dir. '@DIR');
* x. k' \6 O/ v- ]$ G( o  }
- T" ^* u( m# \" }  if(!is_dir($dir)) {) H" e# X3 q) C, F/ @- S
    #mkdir($dir);
1 l% b7 j: `8 y4 z7 G* B8 p    throw new Exception('Create local directory for cache, ' .$dir);* X6 C4 k8 K3 o* T0 g$ k
  }' r% K- l0 _. f& K. L
  return $dir;! o( Y; F9 Q4 T# S6 v
}, ~2 Z- U7 T3 \2 B* v) b
 
) K$ ~; _/ u" D8 N+ efunction v_cache_file_set($key, $value) {. j) h6 H! |) [2 U
  $dir = v_cache_file_dir();- e' r7 @; [/ ~# ^) M2 I
  $file = "$key.ser";4 e) r. p5 ^" E4 O
  if($_GET['debug'] == 'test-cache') {  S$ g8 S1 K) N# q3 p
    drupal_set_message($key. '@FILE_CACHE_SET');- W: n' ~1 p1 y
  }( X0 t2 m1 H' x6 t8 f) z* q$ R
  file_put_contents($dir .'/'. $file, serialize($value));
) H, `; p6 J( G- f0 O' U}6 E# \5 K: h' q8 @1 q) S
 1 U+ [! }' ?7 R( Y
function v_cache_file_get($key) {0 W7 M* e, ~- Z1 m/ a1 ?
  $dir = v_cache_file_dir();
+ J* t7 T8 o& T7 K 
7 D% q, K2 @0 b+ h4 `) |  $file = "$key.ser";4 a6 @! N$ j' \+ c
  $file = $dir .'/'. $file;4 f, j2 _& `& m+ \# U
  if(file_exists($file)) {
% U8 _' d) e$ R+ e. K9 i) j     if($_GET['debug'] == 'test-cache') {
) y! `6 R6 C  V! C# V+ F8 {0 J8 J# T      drupal_set_message($key.'@FILE_CACHE_GET');
& q4 V: w5 C4 V  ]5 J  z+ I. b     }
& t+ E# S1 b6 H5 J* B    return unserialize(file_get_contents($file));( }" l; `% U* d  }. B, w7 C
  }
) B' p+ ?% l3 O" f  L7 \' @/ i0 ~  else {
, T  Z) l$ V; N8 y' L    return false;
, L6 k6 J3 w# }% D$ Q5 j) d  }
& e$ a; U! h( f  Q1 @. j) z0 h}
- l+ B' G8 B" i( A0 S, G7 D / ?. k& X( r' |3 [2 F- Q
function v_cache_encode_key($key) {
0 e7 X. m4 i! K5 z+ b9 C( o& F# r  $address = $_SERVER['SERVER_ADDR'];  n# B# q! x% t0 h. i
  //$key     = str_ireplace(':', '-', $key);* m* [( ]/ y; M# i! Q
  $key = "$key:$address";
: r' V- b/ j/ s  return $key;( Z* }" A/ \3 }" c) G3 b$ a! f/ g
}
$ e8 r' h, h5 U- T# t# V: G ) G. R# b7 O  w$ \
function v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {( n  r  z# T2 c  ?
  $key_mem = v_cache_encode_key($key);
: C% F: f2 u5 K% ^; w' h+ d& U  if (function_exists('apc_cache_info')) {( ?* s$ L' c1 h# k" I
    apc_store($key, $value, 60*60);//1 hour
9 X. M) w/ q* G# ?' e  U7 N+ {9 b* ?    cache_set($key_mem, time(), $table, $expire);
( l3 ^* g) b' R9 t3 t8 g5 }  }
9 J+ H; c2 K# \  else if (V_CACHE_FILE) {( ?6 Y& l0 s3 c$ O
    v_cache_file_set($key, $value);//1 hour( a$ B3 p0 b8 ?- l
    cache_set($key_mem, time(), $table, $expire);
, ?1 o  ], I/ z# S+ y6 T  }) U$ D3 r. u4 D! v* B
  else {
' A, b8 c; c$ C  ]2 J6 {8 [/ u    cache_set($key, $value, $table, $expire);  x: M; E/ ]# y: H
  }
! E! \  k8 a* @: e/ c1 K2 a}
5 D9 f8 o9 e( n" |8 |. e' n 0 T( i: C1 e+ Q, O: y
function v_cache_get($key, $table = 'cache') {  Q# F8 V( g& ?
  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {
. e- B. Z/ g* W6 m    static $static;
9 J. u$ i* `7 D6 k! y, `9 y  _  {    $ret = false;; n8 |: [( Y* l8 m% S4 D
  if (isset($static[$key])) {3 G# x# k7 W. w  s1 ~
    $ret = $static[$key];
/ Y3 W6 P# }' `& k9 ]9 y( ?2 B  }: k) S1 M0 m$ s7 y+ k2 d
  else {
8 B/ S! h, A# t5 n4 ?. W   $key_mem   = via_cache_encode_key($key);* `# I! B+ h6 e0 A& _5 t$ _* a
   if(cache_get($key_mem, $table)) {) U/ p6 s- }8 x1 Y
     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';- U& Y: O9 c! `# @8 K
     $value = $cache_callback($key);
* x$ K8 H7 w0 R7 x' `     if($value) {
& D, _3 B2 [5 I% Q: X  I( B       $cache = new stdClass;
4 Q( h, [" K3 V       $cache->data = $value;
# ?+ O  L' y& H& i0 t1 P+ ~       $static[$key] = $cache;! \+ H* [6 Y* z1 n2 z
       $ret = $cache;
+ Y9 S+ [( F0 ~: ^; N- ?8 u     }; b1 c. o) ?1 ?6 i% L4 e9 R5 H
   }3 k2 H' M7 ~1 F# a& B
  }
- [- r& g1 [1 s4 F: ^1 a; ]  return $ret;
, x4 I. d7 L1 W+ C) T) F }, p6 W% Q; |- N( l3 l' q
 else {( Y6 I! I2 q- v% @9 w3 Q% G0 B
   return cache_get($key, $table);
/ Y& D4 ^* k1 z0 s! B  }
1 k2 z+ O2 Y) f7 e% s# P}4 Z2 H# A7 r$ r* b2 U5 A/ o! ]
 
5 D5 v3 y3 G) T# S" P2 Hfunction v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
; S) o2 F1 ~/ g$ b9 d  if ($cid) {
* L7 r2 `! C) Q0 Q( P8 k    cache_clear_all($cid, 'cache', TRUE);% ]- ?0 z$ e4 p: U6 x
    //apc_clear_cache('user');5 a- o$ ?* H6 Y) s# R* h
  }
5 K! w# M: b* O' S9 a4 X- 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, 2-15-2025 09:09 , Processed in 0.357608 second(s), 112 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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