国外设计欣赏网站 - 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
" h; t, R9 ]' m" y" F3 v201( N& q6 i7 ~5 f' h6 Y$ E8 R
2023 v& {0 Z6 c4 s* q( Q" P- v- Q- k) f
203+ w2 w# U, _" C& k! K
204, E! S9 c- w8 O6 P* p, t
205
; S9 Q$ l  ^9 f! u0 W0 C206
8 t" q$ N& i6 t; q$ P( [207% \2 V* C  E( r4 C& r; u! y) Z
208
) S5 q3 R( o2 }209
! i3 \3 Z! y/ V$ n! {2100 Z/ a- Q' p  `: }: n! ~
211* M4 x9 C% c5 W- ~6 A3 W. F3 }
212$ l7 M, p2 ?9 k0 d1 e5 O$ b
213
7 ~- ^2 k* f; z214
% _6 i- a) m! x1 @  g# w215$ c, `: r2 Q# P+ H. G
216" x6 l9 b9 J7 }( E
217
% R! A( v+ m  M6 U9 b, P2 }, N4 [218/ {6 T0 X  z+ {- r
219
+ L, M4 A( O+ ]6 l3 ?5 L) e2202 y( v) D$ I; U& U. ?
221
1 X( N: E  f: D: B2226 v, o# @9 A4 m) j2 i
223$ N4 j2 K3 m: p! i6 V, r+ I9 {
224
! B, ]( B5 Z" G9 X$ r* S7 U1 o7 i9 |2250 C4 M, _8 L- j1 p8 \) j
226
+ V( ^' R; J8 Q5 P# D0 c9 C227% P/ l! N/ L8 {
228; c$ _8 n  w' w: |! W- L' n- e
229
7 E" h( _9 h. p( v) Z230  k+ K( C" c% {& G7 {( a
231
$ e5 o9 d6 M7 |; q232, ~: q0 N6 ]4 p* j5 n
233
) R* l, i9 X6 s6 V# d+ ~234
! e: h  M- m/ s3 ^4 ]/ M235
% C6 [& i  Q4 H2 P, u" O% n2 {9 i236, m0 q" V# f) x) S
237  b# u/ L3 a' H! m+ J  g
238
$ E2 K/ }* {- M' F239
6 r3 K! H4 G5 o$ J/ C  p: c( h7 Z240
3 P5 _0 z- n$ |1 P2 f241
/ W) h& ^  Z6 h+ ?242
5 A+ l6 n' g2 _- T$ E* f) \. `& t243
  |9 A4 ^+ l- Z) y9 J  y244
: l! a7 e8 E- U245& C  v. K: c; A& A
246
6 F2 M4 X$ m; |$ k+ C247  W$ d6 w, R  F
248
3 o5 v7 S, V: _1 Z- L  @249
4 u7 y) V: B4 i7 C0 ~2506 f+ ?  d2 P, \6 p/ Z  J3 M
251
* l) G! X5 m% B& I1 T/ P2528 e2 E3 q! F1 E9 V/ I: i1 V& ]" G
2537 a: p/ C1 d; B
254
. [5 B' g8 |* {3 n255  T7 Q, o# d5 p6 f, g4 i) C
2560 f3 v1 `! I; B$ x* S" b- g- Z
257) w' ~' r: t, H0 Y
258! [7 P: V/ f" O4 [% C' Z
259+ O: o( M. C# }! a2 e, U
260% i/ y8 B# P3 {+ {3 ~
261
2 a& O$ f9 j$ F6 W) O! a4 `0 t6 ^# K9 M262
4 {' h& W* S- D8 m# j' Z263
2 K+ P" e" h. U3 l8 {+ C! k+ A264
7 _2 l9 q( I4 q& Y265
: q1 l. u4 L( W) R5 k) w266
2 U% g& Q9 l8 i& y5 u( H9 k, ^4 z267" |  G% a6 O+ g4 c2 {- e' w
268+ d) a7 W, F/ ~1 J- Y3 a
269/ V$ w! R3 i3 G6 E4 i
270
, w4 o, @9 d4 E+ T271$ L! H" _' F3 l; G
272
# @2 u; {. k2 ^' w+ I8 g! v1 ~273
3 B* L2 e7 V% d274; P$ z, T, e  a! y$ p
275/ l/ s* d9 i- C8 F' D# {
276* Y3 ~8 ^- b% D) @; I) K
2774 n$ p5 `9 Y1 Y0 a  ^' a
278) x2 S" s! o  I1 J
279
3 |* W7 b1 p1 ]% K6 o& Q7 l280
  M  ]6 q5 y$ o& q3 A, G( G) s1 ^281
5 N) G( r  e0 e  [2826 D. M$ u+ }  R  U- H
283( U1 @2 O: R3 d0 g8 N
284
/ r; f( r$ v1 f- j: K1 }3 P285
3 e2 L+ v% U' |; I0 i, g286+ p& `6 y/ P4 T. Z3 f
287
4 r7 P+ g) v+ p& ^, j( y288
, F# L% k( B& y289# f9 t4 X; b2 y4 U3 l/ {) {$ {  c
290
# v/ p8 M% @. I0 ~5 [291
. n- v! N6 K) [9 D: o+ k/ M) m. Y8 H292
# e9 q& t6 [  s  t' J4 c0 e2938 b& y& X, E; ^3 G. t, g( N
294
8 s0 \; W3 V# \# l- N8 L1 z295" v6 d" R/ g2 r+ B2 s6 K
2961 X6 R, B+ {6 C/ f8 \
297
) d' I- F/ J- p! e: x* |6 L* Q; I2982 v2 i. [2 ~3 B; q
299
+ y$ f. V5 N2 ?# m( k4 N  ^7 y300
" Y9 O" M) K8 W! N7 B( K' b- Z301) M/ Y* ~* i8 Y$ ]& K+ Z
302
/ N  [7 F* }% R7 X3 s* R. U& t8 ]' [303( X4 l, h, v7 P' P5 Y
define('V_CACHE_FILE', 1);
0 C% ?" t' v, O! a 
, l7 f6 V5 O1 h1 c7 L/**1 e( V8 |4 N1 S8 F/ F0 A) T
 *@important Create the cache folder to store the cache data firstly9 ]$ {8 R2 b  \: I' P& F) G  D
 * x* i; E8 \6 u3 I8 ?; B/ Q: A
   #create memcache local cache folder
; |6 u7 G9 \1 @  L9 L! W   mkdir memcache ; sudo chown nginx:nginx memcache
) k% K5 Z0 i- C6 J% l; b 8 l! x6 \+ ]( d- `
 */
6 F, F5 G* r, e; H$ H/ W) v6 xfunction v_cache_file_dir() {% M# W# u! Y  i' k
  $path = dirname($_SERVER['SCRIPT_FILENAME']);  G9 \$ i1 p1 v' q; F, E$ }; a
  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';
9 h& y5 W: c; Y4 w/ D2 h  $dir  = rtrim($path, '/') .'/memcache';7 M7 y) h) @! m: q) w  V8 L4 \
 * h6 @( j3 l. P  T7 \/ f: f
  if($_GET['debug'] == 'test-cache') {
9 v4 P( ^; z' t1 k' {! ]& ]    drupal_set_message($dir. '@DIR');
1 s; z/ M# u- M* G0 p8 T7 [: t/ @4 N  }
6 x- m. [' l. j; H  if(!is_dir($dir)) {
) p* I$ h% B. y! m5 I6 r6 e    #mkdir($dir);* ?/ y- V8 O4 j" G2 @
    throw new Exception('Create local directory for cache, ' .$dir);. j6 o8 n) d' I6 h, W5 D
  }0 c2 P  h- \; V3 @9 a2 B
  return $dir;4 p, Z8 S7 R) G/ k: z& }, I
}
9 _4 E6 I( F1 U6 q1 v4 a" h7 g2 c$ k0 U( i & y+ w1 c  C; c9 M" F) g! ~+ i
function v_cache_file_set($key, $value) {: v/ A5 Q/ H/ B4 U* i  t
  $dir = v_cache_file_dir();; f! R1 v4 k) Q2 r2 p5 H
  $file = "$key.ser";
8 E+ P5 g( r! }$ G$ C+ L7 J  if($_GET['debug'] == 'test-cache') {
" l+ ?1 F5 f# n% s/ _4 y    drupal_set_message($key. '@FILE_CACHE_SET');, L9 W! t- P3 N; o
  }
, B0 R. \! P# Z' w# A' ?/ X  file_put_contents($dir .'/'. $file, serialize($value));6 ^8 i2 `1 [$ M. m) I9 I* Y1 T! t6 P0 e
}
0 P9 n3 g# H: Q) v5 v# `$ C " x7 M) b. X, b! s  {. l* M
function v_cache_file_get($key) {
; A) T" D0 {# Y5 `  $dir = v_cache_file_dir();
- D4 H, E) z$ U   @0 u- c0 `+ }& A: f: ]8 K1 N! Y
  $file = "$key.ser";; C. F4 A& A( d' H3 b# p0 J
  $file = $dir .'/'. $file;" R% X: x* P: F5 \, o. @7 A" N& u
  if(file_exists($file)) {
3 t2 M; d; w- [. I( A     if($_GET['debug'] == 'test-cache') {$ V% I( x4 T3 ^; l
      drupal_set_message($key.'@FILE_CACHE_GET');
' S! Z4 L: K/ I( [9 S5 E     }
0 M2 I: m9 ^. Z# a* u7 j    return unserialize(file_get_contents($file));
& `  a. J7 Y! m$ r% b( t7 g+ t  h  }
( p# \( ?5 M$ ?- l9 h  else {  \  {: Z; b* r" l; i8 n
    return false;
6 b) ?2 t- I1 E. ^0 g  }
- @' ]0 p! r$ n6 X}  d1 Z8 ~- M6 ^
 
: P$ Y' T( y/ n, {3 G+ g5 `function v_cache_encode_key($key) {
$ {0 `) D7 [7 g# U0 p1 d. x  $address = $_SERVER['SERVER_ADDR'];
( A2 L) g9 R# T# `  //$key     = str_ireplace(':', '-', $key);$ m( v/ P3 d6 I
  $key = "$key:$address";- j. B* ]* P- [, A% M, V1 y
  return $key;* B" L. J) U& P4 d" z" _+ ?
}
0 D6 E5 I" Y6 F' u* [ 
, U! f' h/ e2 }) F: X$ b& `' Efunction v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {
7 J$ F$ _1 z# p3 h$ f4 a! J  $key_mem = v_cache_encode_key($key);
! R1 b7 `% m* p; F+ B9 z6 b  if (function_exists('apc_cache_info')) {
  @* U+ d; p1 b, S# n8 r/ X, w    apc_store($key, $value, 60*60);//1 hour
/ ^1 Y; s9 W% i4 k) w5 [/ Y5 P* p    cache_set($key_mem, time(), $table, $expire);% B$ f: }4 e1 u6 U
  }6 L' E. o' D) U3 M: B: t. P7 i
  else if (V_CACHE_FILE) {4 Z9 n/ _. [) {& g- o7 N" U
    v_cache_file_set($key, $value);//1 hour
5 W4 f4 S6 |9 \$ _    cache_set($key_mem, time(), $table, $expire);0 t& J! M2 J' {# E
  }$ X* h0 i5 i/ H7 z5 J# d. ]7 x* Z3 S
  else {
# b. V6 N  Z. g    cache_set($key, $value, $table, $expire);
* T  G  H; X3 d  }& Z/ Q! H; @# T$ `
}
6 f4 S' |$ S- q) ]2 { 
# z/ L% B) m0 @function v_cache_get($key, $table = 'cache') {
3 U$ S& X2 d* R0 P5 L/ g  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {% T3 ~8 ~& `: I* f, c, @  ]2 s
    static $static;
, r% e" V1 S" _$ t' ^% I    $ret = false;/ b; q; u! e1 `7 G" P: a% V
  if (isset($static[$key])) {3 O; F- J7 x3 ^1 H
    $ret = $static[$key];
" M0 x) p- b9 i7 ~+ Y% N  }
) t% m, L$ x8 t/ t; w  else {9 k% ]# j  x/ R0 E
   $key_mem   = via_cache_encode_key($key);
/ z. F4 k' K/ U   if(cache_get($key_mem, $table)) {, h9 c% A. J: s) i$ T
     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';
6 @8 P& e/ h* K% i+ y- f     $value = $cache_callback($key);) O: m7 l# ~( b8 ~! Z) W
     if($value) {( a: ]) W1 _- \! [$ y
       $cache = new stdClass;
  n. }6 Q0 L& T" W$ |. ]* @       $cache->data = $value;6 X- |% c, c) e' [% k6 g" ^
       $static[$key] = $cache;$ U& Z7 ?. S, ^- i& o4 Z
       $ret = $cache;2 r6 S+ s; b& }% d# F# l
     }7 I( Q$ _& [4 i9 w: {, D
   }" N# Q3 q1 }) I& U. _: o+ J
  }
9 w" ^" a& G, K7 p+ V  return $ret;
& a+ e; e% X3 {2 M2 \. Q }  r$ k9 ?1 \/ u4 s: f) S
 else {
+ j, n$ z3 L! u& K6 f' q) x   return cache_get($key, $table);
+ n8 {+ O4 g9 J8 Z% q& v  }
( g# Q# d/ L- u" o}8 N: y( F! _9 u
 ( O5 D1 m4 t: ~" c
function v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {$ c  g& _. V7 t5 M: O% [9 U8 d
  if ($cid) {
: @# s8 Z- y" j    cache_clear_all($cid, 'cache', TRUE);1 E( s8 J# D  V
    //apc_clear_cache('user');
( k" z# e! O$ T# m) D3 _  }
" _! c: h. }5 S5 W# f9 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:57 , Processed in 0.409194 second(s), 113 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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