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

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,微信登陆

搜索

[Drupal优化/SEO/环境] Drupal性能优化方案--自定义缓存之共享内存--Drupal教程

[复制链接]
发表于 4-20-2012 21:36 | 显示全部楼层 |阅读模式

对于高性能、高并发软件架构中一个重要的优化策略就是,能在内存中处理的决不能放到外存中。这里外存包括:网络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- r% D) B* @0 T7 L+ b  S3 H
201
6 {3 w5 Q/ \& Z2 {) l/ l202% N0 M7 f" {, H' u
203
9 e( i6 S  y' G' e204
% l! ~0 _7 }3 ?5 b205
8 @+ `1 b* o4 ^' o/ \' M4 u206" `7 E1 D8 }& P& o9 C3 c: s# p- j
207
4 K( u* ?% L6 r# C* c7 u% @# G208
$ ?' ]2 K8 F, o# L; t  X$ `4 I, b209
8 x, u1 _. E! f2 M- t210
: {$ {  q4 ^- U2 e8 v9 u0 K5 X211
4 p" U* l& `, J! Q) q212
8 }9 |% I  v" k% w213
- v& H2 l2 T0 T' O214
' S( Q6 _1 ~4 X215
( n1 K# G  G/ S$ ?1 j216- T0 w- Z. c7 [9 n& L% f
217
, t- j7 C0 x( |8 W9 c9 I7 b! p3 b2182 x! y! q& ~) i! k2 |1 h
2190 E( v) Y; I, H; C
220/ [- P3 z9 H6 c0 d
221
; Z1 {3 @* @9 c; o# S7 A222# w8 j/ O' @6 c4 ]. ~7 G" }5 ^
223
4 H) X8 `; F  y# L5 j224
6 X+ d4 R0 [3 D7 Z) K) p" A/ a225
; [# d6 ^" a" ^8 Q. @9 S226) T; u1 k& b; ]4 C3 d' n" T! t
227
/ V& s% N) T0 B) B) d228
* ?: c6 E% ^5 n( w# k7 k' x229
, |) u9 }" u% p: H0 n5 X$ l1 B2305 c$ y) y- N) V* ^" S2 }0 b: _6 @
2311 f4 v* I4 f, O1 a9 q
232  `6 L* n0 A0 t6 m0 o  K
233
$ ]* C0 s( r" u# W0 Z0 |" n2340 e3 s) |; h5 p& M# s
235
+ F/ V& m- _0 o  p+ Q7 e236
+ g3 @* l4 D6 `, w( ~237  R  V4 S- A8 {$ ~1 U' C5 {' s
238% P; h& ]; W  z2 r
239
9 }% A* T! J. t7 _2402 y* y7 p6 V( }1 e2 C2 P$ V1 h- c
241
: ^; G) k  Z0 P* C242
. \0 O3 J) V. h+ C8 R% p, Q243$ `3 M! D) k8 Z( W* X
244
' _6 j5 V1 a3 U245
  _. N. r. R- `5 G0 W246
) {1 R2 t* N( L$ z2 q2475 K  g: d* t: E' y& i
2487 {( j" L2 G, e  f1 a" F
249# U. d7 J, v% a- q; t5 d. a
250! A  t/ I' Y) `  {: |, M2 E# P  X
251- X  q0 _* b* `: v
252
6 y# E! O' f: F+ d8 q1 q253
0 s! t  Z" N& u; k" k254$ M0 {$ w, H3 M% {8 H+ X4 p
255# n- Q( e1 U7 Q8 q" C
256* U4 t6 e1 s/ g" `
257
/ [4 j, H0 z  S258
& n) _" S3 n/ J' Q2 ]! X259
. U% ~- J; h' X( w- D260* A+ q9 x3 D3 v0 @+ N9 z
2615 W1 z7 [" c6 j' H& w
2622 Y/ `' [# c. _( v; `* }
263
; `: W2 |& Z7 T' ?3 r& C# y0 H264: V5 I# Q/ h7 {, g
265" U' q: ^5 {2 ~% \, S
266+ l5 b, h: J) ]/ g7 S, K
2673 r  Q* {' t  ]
268' n: a* V9 f5 K* i5 o
269
* m, o7 ^1 D' }3 r- ]2707 a( g, {( h/ @2 o
271
) Y$ ~. m  X; m# E$ K+ u! u272/ f! G: ?' U( I# c8 n- D8 [
273
( x& e( ^, O& s' @9 ^6 V$ y' t* Z. f274
/ O. V: W! v  L0 L1 k% U2 e# f+ Z275' V- m7 I5 R( F5 y
2764 P$ |* H6 q7 R2 b/ x
277
* S% k$ |% d8 v2 G$ I. d7 v278
$ S: _# p1 v: _$ U279) O2 l" K5 W9 }4 c
280  \; }0 _  }/ {( h! r/ b
281
: A) f4 X5 j1 g6 e, |9 y282+ s( L3 z) o& O/ D+ @1 O" U# c; b
283
) o+ v; u+ L( t: m) ^284/ K; y& |3 H/ g
2854 ^+ {2 l' @& x+ P* y" L' M
286, @" d6 r- |+ a! i# G) @) G* [
287" z; s! x& o- p
288
3 ]  _3 f4 `3 {! o4 f& I2896 J9 S0 e% s( M4 a5 O, D
290
- j( g5 ~* a5 ?291
1 ~# y: a+ H" Z1 I292
! `0 M- x! e4 H; e# T$ e293
% s5 i, {( W2 n, t# {. v294
: N( I: h6 x/ t- f& |/ Y2957 V$ m' v' s5 D$ H4 G
296& H* N8 }0 s" U; y
297
% Y+ f$ m/ n' s* g" t: i2980 _8 q/ T: S4 F' k+ y
299
, q! l1 [9 V$ f. t3 l3007 M$ U1 j+ w, A( Y( d9 `6 y
301
" T4 V/ @0 |8 W# {5 f+ f/ ]1 g3020 u3 A& F6 [* l. w5 p3 L5 r+ I
303
, e& }% k$ H0 V: a& I
define('V_CACHE_FILE', 1);
9 C# o% y( l) F- j" Z 
* E& r" [2 U; j% P* C' v/*** f- p; j9 w% z
 *@important Create the cache folder to store the cache data firstly
2 J; M7 U, |0 r# e- p 
) s8 x* ~1 r# O1 ]   #create memcache local cache folder
1 L: K4 x/ }) }& O   mkdir memcache ; sudo chown nginx:nginx memcache+ w6 r. y, P( {  B1 e0 S# R& m
 ! @& v. K1 @/ E& z6 L! S$ T
 */
% z# t% t( Q( M* P0 q/ }" @) Ufunction v_cache_file_dir() {; a" A; W! i5 {3 V7 O5 q
  $path = dirname($_SERVER['SCRIPT_FILENAME']);
- ~: ^! |% Y1 U7 D+ T  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';
1 d: C, E* s' `! p  $dir  = rtrim($path, '/') .'/memcache';' C% U' \$ L' R8 l
 $ h7 g; @6 _7 t" W- I" e
  if($_GET['debug'] == 'test-cache') {
) P% p0 Q4 O' L: O' p    drupal_set_message($dir. '@DIR');
0 ?5 y7 M, B6 w* k5 F  _  }
2 C( ~+ z6 g- I) E% w) i  if(!is_dir($dir)) {; l9 S. [$ i- Z1 D/ v; w+ \
    #mkdir($dir);& I9 d; x+ z. t% r3 H
    throw new Exception('Create local directory for cache, ' .$dir);
4 G- G; a8 A; g0 `% a9 m  }+ n& g8 o: l' B% ?
  return $dir;
8 E5 R9 |1 O1 k3 f/ S. b}$ @& `" w' \" G! y
 
. F4 Q0 U7 N: t5 Cfunction v_cache_file_set($key, $value) {6 m# _  U" S, J, x3 m7 E
  $dir = v_cache_file_dir();
/ `* O) j9 ]1 N1 j9 q) z, Y  $file = "$key.ser";
4 F" z& Q5 L! f7 V0 T1 e! v  if($_GET['debug'] == 'test-cache') {
3 v; |- H8 x- o7 \# p    drupal_set_message($key. '@FILE_CACHE_SET');
4 i* t8 D9 a" r2 d  }
5 D0 B7 t6 q, K" b  file_put_contents($dir .'/'. $file, serialize($value));' q6 ~2 Z& z* Z, N/ k
}
! a; @$ R6 i9 S6 y4 n4 o- M6 Z" V 
* p. r+ L- [" z% K- m" Ufunction v_cache_file_get($key) {. T3 D( \& c* f7 W
  $dir = v_cache_file_dir();
: P2 S9 a" D3 D8 s' w3 ? ' T2 \6 O$ s6 M
  $file = "$key.ser";
/ D, w$ W3 I! Q6 K& K: I. k  $file = $dir .'/'. $file;8 m& x5 |: |  T- g" {
  if(file_exists($file)) {
$ h" L6 z, |. Y" ?2 m     if($_GET['debug'] == 'test-cache') {9 C  R0 b: |- O5 A; u+ ^
      drupal_set_message($key.'@FILE_CACHE_GET');( Y! ^3 N; G' w9 g+ X
     }8 ]) _* E  L4 k0 [( {% G4 [
    return unserialize(file_get_contents($file));0 M. H) @# L$ [* K+ A5 l4 [
  }* e2 }. o) b9 o! S; j# X/ ~8 Z8 i
  else {, f1 s; q5 r$ M# V! A1 s. \* Y8 @
    return false;" B$ z0 M7 f; b1 r4 ^* g% I1 _
  }2 ^7 {8 J7 F  z& s. i
}
. L# `" P+ W9 Q; B 
* o; l3 X/ c+ j5 H6 i0 ufunction v_cache_encode_key($key) {4 `4 V% N9 t: w% I, f
  $address = $_SERVER['SERVER_ADDR'];
+ ?, ^- \  Z" _; W5 r6 m' Y. L5 m  l  Z  //$key     = str_ireplace(':', '-', $key);
) c6 ~8 k) |8 A9 h) N& m  $key = "$key:$address";  i9 N  C) Y9 j* B
  return $key;$ t: h9 S5 f0 t3 ]! F  z
}
, m0 D+ u* Z' ?: w2 G$ s& x( S 8 {6 G4 k7 v/ u) N) ^
function v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {
. o6 J( k) p: c3 Z- U0 s/ ]  $key_mem = v_cache_encode_key($key);1 D/ `4 d3 ~# e6 N
  if (function_exists('apc_cache_info')) {
! J( r) y& a  e0 ~    apc_store($key, $value, 60*60);//1 hour  z. E) q% [; i* O# O2 e1 f/ g( `
    cache_set($key_mem, time(), $table, $expire);+ `, b/ c9 _' |4 A$ R" r+ `
  }4 I* x( @* a% [) Y! F4 H) t6 z9 ]
  else if (V_CACHE_FILE) {* P" G4 |! W/ ^+ C) l
    v_cache_file_set($key, $value);//1 hour
6 ~" f3 o& F$ U( O5 Y" [' V. Z5 ~    cache_set($key_mem, time(), $table, $expire);
5 K# y  b# X# Z+ G( l) v5 i  }9 u3 q! |9 @7 O: a; z" _  S( G* z
  else {
' i" O& s/ k: k: z6 E! r9 L5 O9 n    cache_set($key, $value, $table, $expire);
! C  J% a) g  D$ x# g5 M" B  t: I  }
  e# [" O7 }$ E}  W  X( w  B- n1 @
   Q! V/ v! w) j0 b
function v_cache_get($key, $table = 'cache') {
" Q$ j: `! V8 F& O! D" a; u  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {
) q# C; G8 \; R& S; a    static $static;
: ~+ ~5 l3 Y/ O1 o* H& L7 C- y. r    $ret = false;
6 D, Z! L% R; w% J  if (isset($static[$key])) {
2 H2 K6 `7 S' [" C& J    $ret = $static[$key];( o, x7 q- B/ F/ d
  }0 }' n! W- P' o; p4 O0 c
  else {1 A* @- P5 }% B
   $key_mem   = via_cache_encode_key($key);
' l9 _1 j+ t" ?7 m. `. m   if(cache_get($key_mem, $table)) {+ A- i- r# [: G1 b
     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';8 n; Z. c! I0 E: f
     $value = $cache_callback($key);
/ u  j; x1 h- S  c     if($value) {/ z3 k2 D1 x' {" N# P
       $cache = new stdClass;
. t+ m9 L2 |; Q! z& o       $cache->data = $value;
( e, K1 M8 z; I# F- }       $static[$key] = $cache;
; V' h: o& s6 I& W# J       $ret = $cache;
4 V* `$ W7 ~) s; c7 D3 b- J4 w  v1 w     }
  w) }/ `1 \: E+ T/ W   }
; k! s  }2 K; q% M1 q  }1 z2 q" ^* T' d1 b6 m/ a4 o" t( M
  return $ret;
/ H6 D# D' d$ l: ] }7 N7 v" n( Z6 j* e8 I; t' e" F  v
 else {# `6 W. Y. y  [1 }6 a/ [7 z& T3 N
   return cache_get($key, $table);
, V# h7 q+ R. y- j9 h1 L' s* q* x+ o" w  }
* s9 Q7 P6 x+ S( I' ~}; B  o) K3 L8 k6 t* I1 ?" b+ j
 
& C! g' u. u+ t) H+ o; {& Jfunction v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {" m: r4 c* D1 }# ?6 l
  if ($cid) {
7 ^( g  Q8 q7 \    cache_clear_all($cid, 'cache', TRUE);% T$ H- S" `: B) @; v& Z8 E" t8 k9 Y
    //apc_clear_cache('user');
5 w7 o) [/ @3 ~. o  }5 L' v0 N( t3 l6 [/ s4 k
}

添加了上面到代码之后,我们需要修改一些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-21-2025 07:55 , Processed in 0.323855 second(s), 27 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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