国外设计欣赏网站 - 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(内存共享)、文件。这里我们重点选择文件夹,因为文件夹正常是缓存在磁盘上,但是我们可以把这个文件夹挂载到内存上。如果内存不够可以取消内存挂载,这样操作起来比较灵活,也不需要修改任何代码。

2009 Z9 t' f1 d1 C) \
201
. e* U) |/ y* E0 n2029 u' f1 O" N; h
203: v, ^8 {# L) ?
204# `1 I8 C- s( z
205. U7 z6 _2 T7 G& K
206
7 d' }7 u; b4 p1 o207
6 G5 ]. I, F& O/ F- r' B9 E( z0 F208
. {# y: o6 G' v. {+ _6 ~* @( t3 Q209
: q# [' p8 `6 N; m4 g7 |2109 q! z+ |; w4 ^) l! J
211
. ]3 F2 L" ~, e9 M" b2127 g- R( a" o3 s. u& N' Y
2135 \' a% B7 q3 e2 W
214  M2 v" v! q6 p" P5 }
2158 O7 T" Y5 M9 E$ t
216
& ?( [) p, P$ l217" X- x$ @# m1 Q, e& e+ e# R- I) o
218
. ?* D  T. i- |! ]1 z$ V6 a: X219- e4 B3 h& _. a8 c' p* ^
220
- y9 i9 S$ r/ u- x- p1 |221
3 n5 K  |2 o& |222
. x% D3 X( A+ A4 A+ w- K' s223' A0 O( N* U2 P0 s9 P' ?
224; ]7 t5 }/ }( n8 p& M& n) p
2258 Q3 {5 ^+ d) v
2268 g) x" }0 q8 q2 z+ n8 `; h
227( v) f0 p9 q7 M! @
228
( R; v4 N% a0 ]7 x* d229
8 \/ _( O  Y5 C6 a6 n: n( k230
6 k  u9 O* E8 H: D/ M231
/ K, G* P( }0 f0 [: {; ?/ ?+ W232: H# [3 E: Z# c; q1 e4 u5 N
233
7 r  j7 i( ?% I3 q234/ y$ H6 k1 V! Q) d  q2 F
235
: Q5 W# R# g3 k0 p& ?236( m6 q4 y  e/ o/ ^, N6 k$ C1 L
237
% E8 M! Y1 `# S$ K2386 q2 `8 V: k. e- q, b- {
239* ?) H9 `7 [* h  F: |" ?# q
240$ z# W4 S3 U: d$ a- S8 M
2418 }' [- Z+ m9 W( [
242
/ q2 `% t2 y7 A243
$ w' C  j: Q' e! Q- i$ O244% ^% q3 d8 ~: }$ R1 F. h4 s
2458 O" u: I/ D' n" @
246
5 X$ ~' ~& @; O# @247
: z9 [/ ]  p% `" P248) v) C% H' k) G" s
249
' }2 V0 ]& {/ |: ^9 m* U1 E250
5 O; ^1 P3 d2 E4 I8 q" o8 V251
. K! u2 m0 W& _/ ^6 S( q2522 t- }( m" H* y/ W9 h8 L! e8 V
2533 K/ W- a4 F; r
254
5 M# a2 J3 d8 T0 w) S/ M  {255" m' h% z) `% a, z) g$ Q
2562 M) [, l- N5 W# {! v2 ?- ]! [7 `* W
257+ j  o7 h& H, o4 J. L2 C4 M5 D
258
5 g8 x$ [' [$ \. _9 S  S259
% S) n6 R" [: |1 B1 X$ `2 K( [2 h2609 T" x9 S9 G' D: v% [
2614 ~6 `1 F0 J8 E7 `) n' e
262
& t0 w5 ^5 v  [. V2 i263
& [% V9 Q9 R8 ^6 a7 X264
8 d& k+ B/ J& \( q265
( I; B# g! A! S0 ~266
. H8 t* Q2 x3 d+ ^# D: `( }267$ d0 p1 |/ }5 Q+ y3 {" y
268
, j% m3 ~! t' u5 m269) M1 a" {8 F8 Q
270
7 c$ a4 M7 _/ c, [" U$ I. z271
' _. `6 Z2 [+ i272+ D& R- K* D8 }' J
273; G  I% ]  J2 R) Z
274
5 J! b$ P: `. _2754 Q8 F% X! w, P" j( T# V
276
, N. Y, |8 C  P4 c5 n/ b1 e277
3 e& d- R/ X' K$ h- [278
& g3 T+ @% L) _0 Y  t" C279
: j# d8 R- F* E280
6 F5 g! n  ^- p! d& {1 V1 L281
/ u  c& j4 L7 @  h- x! |, y282( ~, \' y3 ~' r* F* v
283
8 y3 e% n# q; B284
$ M% W0 ?0 e: |+ H$ E# S. P285- e: e! @/ h' t; s  Q0 j1 d- ]4 e
286, S4 I  v6 u( D( f! y
287
! {& H" }& x8 j( I  u* I% }/ a1 h288
, K( `& y( c& J2 ]6 A# V) z289" C% m4 V8 k" E( z+ ]
290
( K9 l, ?$ E& U1 q- R! j. Y291
$ i9 h4 ]$ {+ l1 p3 M) B3 l292
" S1 y1 Z! d# X5 P293+ W, m) ]4 s) q5 ^& a1 Z$ O( Z
294
$ \' w0 Q4 \' H7 x% S8 X295
- Y. a5 L' E; A1 R296
/ ]; ^4 Z6 K* a8 A+ A297/ F3 d7 y" k# \
298' x2 z0 D# c+ c; i& K' o- G$ G
299& g" y# |! u7 {
300
0 v: z8 m! ]9 L1 U$ y' I" e' L" C301. E4 H" o: P# L3 `1 M/ l8 y6 T
302
2 m. G7 }7 m& o, L: Q303
! U0 v: a% s6 g( n! y
define('V_CACHE_FILE', 1);
" i3 Z2 N! `- S6 S; |0 C6 H " V. z7 c) X, S' v: j7 @- ~
/**0 {& m2 p2 p6 x! m$ ?
 *@important Create the cache folder to store the cache data firstly
  T6 t$ L! I7 `* w 
' o3 s# i' j  t   #create memcache local cache folder
: w5 G8 Z) i# O2 Q9 l   mkdir memcache ; sudo chown nginx:nginx memcache
" L! r8 \# ]; o4 ~7 D$ G # K6 O" s' r4 ^
 */: L0 F3 z& K! B5 p9 b' g
function v_cache_file_dir() {1 N/ I" p' M( A' [  z) }, i" |1 t3 _
  $path = dirname($_SERVER['SCRIPT_FILENAME']);5 r! S0 Q4 N) p0 ~  O* Z+ ^! J; D
  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';
( x' ?, w+ ~7 o: W) Y" t$ ^  $dir  = rtrim($path, '/') .'/memcache';1 Z$ Y! V0 d  a& C# W. R* \
 + t2 q# ?& z3 L8 z
  if($_GET['debug'] == 'test-cache') {
5 s; [# S: |8 @8 G; n    drupal_set_message($dir. '@DIR');
7 c  ]) t) Y% q  }
. r  b9 B6 n2 ~: K$ x: s  if(!is_dir($dir)) {) [, E7 @+ V: ]1 a( v7 t
    #mkdir($dir);
2 j8 a. y, C4 V, u0 l" P    throw new Exception('Create local directory for cache, ' .$dir);
$ S" r# m6 Q3 ], G) U  }
% W( a0 ?* d% @6 r  return $dir;8 Z$ Z- t* ~8 V# a" o$ G( |
}$ c$ j: G/ j9 L$ ]5 c
 
" q" B/ S4 e& w7 Ffunction v_cache_file_set($key, $value) {
/ }1 k7 f$ t+ F/ O  $dir = v_cache_file_dir();
8 w& N% z5 f( C# ^5 N+ r: E( Z5 z  $file = "$key.ser";
# B  r' p+ u5 g1 L$ y  if($_GET['debug'] == 'test-cache') {
! p  C/ _9 d" G( W    drupal_set_message($key. '@FILE_CACHE_SET');9 r7 h) ~# m9 L
  }
% g: l5 x, y: C  g  file_put_contents($dir .'/'. $file, serialize($value));7 k# ]) b0 A0 _6 Y
}. H1 a+ N/ p  G- \6 z% K* {
 
3 e" M/ o' l& L  s1 `+ P) c' E1 W. e( ffunction v_cache_file_get($key) {# `/ Z7 g) ~4 ?( D6 U( r
  $dir = v_cache_file_dir();2 E- I; `" m- |
 
: B  ^: B- k9 H) K+ p! w$ w) K  I  $file = "$key.ser";/ E2 p% q$ I) H' [
  $file = $dir .'/'. $file;8 R. ]) d1 L' Y
  if(file_exists($file)) {* g+ g9 G" T) [: i/ H$ \, I3 P
     if($_GET['debug'] == 'test-cache') {; L; \" f5 T2 R3 }
      drupal_set_message($key.'@FILE_CACHE_GET');$ E+ _. l+ ]% X! g5 }* ~
     }
- P6 `. y" P8 y$ x* |2 \$ e6 |    return unserialize(file_get_contents($file));2 m6 u, o8 |, F5 I) U- ^6 G
  }
' X) u+ u% X6 u* q1 S! q; c  else {
  z! b' g5 z; X7 c! {/ w    return false;
$ G$ w3 n& z' z+ y* x  F) v: e  }
: A9 O: m, {  D! C}
+ T! T( p" k$ k' L7 R3 H4 f 
$ J& |# Z& q& g: f! |function v_cache_encode_key($key) {
8 P2 p3 d& p* N/ b- f  $address = $_SERVER['SERVER_ADDR'];
+ U% A+ R0 o7 I. [" V& u# r5 \  //$key     = str_ireplace(':', '-', $key);: f  \3 N; s: G8 ^
  $key = "$key:$address";
5 e( `- \* k2 y0 [7 t  return $key;0 }, Y6 i4 J4 h0 n' f  |
}
# F2 {" E9 ]+ T) C0 y  v) M ) y  c6 q# T+ h4 F$ T% h
function v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {
% J+ L; o( Y0 {. q  $key_mem = v_cache_encode_key($key);
* u- q$ k$ Q# ]1 B  if (function_exists('apc_cache_info')) {
. ^: F3 I5 E$ \$ P# c    apc_store($key, $value, 60*60);//1 hour0 `. ]1 _" v+ L& H8 k
    cache_set($key_mem, time(), $table, $expire);
9 M0 M1 L- F' [  }0 o* B& I: e: w: B$ |, E* B. `
  else if (V_CACHE_FILE) {
5 Y& S, ~) p  U& e' ]    v_cache_file_set($key, $value);//1 hour: X. G& }) |; e: \. q  P' O
    cache_set($key_mem, time(), $table, $expire);* |- ^6 a# M3 ?
  }
4 ^2 e, E) C# O8 n5 p  else {& |( Q2 {0 H$ |; d0 E/ e; I
    cache_set($key, $value, $table, $expire);
" H7 M: Y  V2 Q/ F. B  }
  m7 n4 K/ y6 C- J}  \+ k$ j3 H: A
 
, m9 h2 p  r2 W* Xfunction v_cache_get($key, $table = 'cache') {
  z( R- c8 p4 Q) Y  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {2 ^* a& B3 r: V9 x
    static $static;1 [5 k' g) n1 k4 p7 l5 S
    $ret = false;
) V5 L* x3 c) x4 d2 z  if (isset($static[$key])) {1 ?* i" ^2 N0 }, `; |7 h
    $ret = $static[$key];
5 x7 ]! V' ?' n6 v7 v9 r' H  }& O1 y9 e6 P1 ^' R9 k
  else {  ?$ @4 i! k% p4 e1 F
   $key_mem   = via_cache_encode_key($key);
* h( Y" |& \% N/ Q& q   if(cache_get($key_mem, $table)) {( B4 F' Z7 \% i1 U+ b, I) b5 B
     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';
& `/ M' N. Z; F     $value = $cache_callback($key);
/ R, q5 G& F* P& m8 D3 F+ S     if($value) {
& ]3 s' |1 u& g       $cache = new stdClass;) D/ L4 S/ n* E
       $cache->data = $value;
& B9 E$ k; v, {4 G       $static[$key] = $cache;; J3 z. [' l: W' }5 B
       $ret = $cache;0 v( d' p0 \+ z4 f
     }
& u" x% o$ R4 M  `7 g0 b   }
; T7 k. z) i. F7 l, C' V& S5 {  }
  U9 X* ~1 r: q$ K4 g& g  return $ret;
3 r% l5 ?; n: Y% f$ J7 ]# B }( [9 v) \& m1 w$ P: y' w5 u
 else {' v; }6 X4 w0 G; u8 V8 y
   return cache_get($key, $table);/ I4 F" e- u8 l: j
  }
4 Y; p# L/ V+ ~4 x+ p0 r}% p' a* R( `6 n
 
8 _" E% t4 E# V+ y6 efunction v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
" ~0 F2 N2 j: @) G. |6 @, ?7 N* J  if ($cid) {# ~% {: P9 x1 d  D, N; Y( X. H% T
    cache_clear_all($cid, 'cache', TRUE);4 l9 j/ M. f. U" g
    //apc_clear_cache('user');. K2 a& h; Q& |* w' G0 L
  }7 p% V6 {6 N; j6 Z; g5 e- J
}

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

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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