国外设计欣赏网站 - 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
; h0 d& v6 k3 z7 N201
' a  ?* d: ^$ U, Q202
$ `3 q, }6 |6 d+ b1 I203
& [6 G, \  c* R7 L) L5 b204
& Y$ ]" N! [( ~7 {: k7 G5 B( ^+ ]5 c5 @2057 P" u/ D; o: J6 d+ E
206& t. L% }( T2 b; ~
207) O9 ~/ f; P& B1 t# ?
208: ?7 Z. @8 W+ X/ S) N. j2 F& X
2096 w* j. Y9 b+ D7 v6 v! |0 \3 x
210
/ P' n; s) r4 [9 ?1 \211% u: Q0 a, g; e4 Q
2123 H  ^( E4 X  B  m
213
( e( n, ?; o' [+ R* }! R214
+ ]2 }. R3 Y* E; W  g& W* p215- H; S( B1 U& w% W% `
216; u0 c0 E9 J0 c% P: L' U4 A
217
6 y, @! A8 S1 i1 I, j) X4 g' Y0 y( }218
+ e' I( Y. W2 v& E219  h+ i+ }! z5 v
220
; Y% L& _7 i" o3 i' [% w  n4 s221
3 Y/ f* J8 e; P# h  `) o. r222( i$ J# Y! D$ w" O5 k$ I
223
  f4 t% g) z% q2 z1 p) k224
/ E  a0 _9 f+ e$ g225$ G1 X1 o, c6 N, y4 n" d
226
# g1 H: T- q6 a227& n, r7 R0 Y' ^" U- P
2285 f  X* u% X* ]5 I9 V3 N( T
229# ~0 {# q1 Z& N7 a# w
230# r! S) X. X3 l+ g8 P& y
231. v% p3 a! Q1 S, a0 {- {2 K& [
232
$ p- p9 o) e' B% Z: k0 |2338 h4 w- |( {/ I2 b* b- P
2340 S2 E0 \4 q. j
2356 m  g7 k" f5 }3 r+ S" I) |1 I
236
4 W4 L7 G+ o1 k237
. n- p$ x- K# n8 M% A3 _5 H238
% m6 o+ |  E* `: f2 \" W239
8 t6 O7 ~  V8 b. M2401 y+ E; E% x& a; ^; w% E
2419 m! w, z! Q2 y( O$ Q6 i2 |
242  N8 j$ t# t( ^' S; v, u% r$ S
243! T% v( @; D2 w8 J  D
244/ S, Q% b1 b# z  `- V0 |
2454 a0 y& W7 `) q1 H; m% K% G
246
) Q) Z/ J0 P1 x# n6 N* D2471 b* G/ X6 E4 Z) P
248$ T" D3 {2 S" k+ @* k0 S
249) E5 s+ K- I; _) }% `
250
+ [8 B0 m- S4 d- P: E$ Z/ p251" b+ R# `6 T, B7 }6 {' q: k; J! [
252
$ k# o5 U5 A7 j; ~0 d6 z5 h+ H9 x0 F2533 C7 V0 m' S# r0 W0 J9 [. t
254
" w' _1 I4 V; T* T0 l: a. G1 {255
/ r4 u# U8 u2 ^& m, q# @  m2565 ?  T( i/ i3 K. {: V; N( ?! y/ Y" o9 [
257, I& A* \2 {7 z9 e
2589 C. ^" c" E% W0 M: P# _
259) x. _$ N8 e: k3 C1 i
260
. l/ F. I, F8 {% e% {2611 C" Q- e- ]& ?5 p' P% l7 X& x
262& c, F9 T$ x# p5 d8 }: t
263& Y# D7 w3 c  i" E. x
264$ g2 @- P1 e7 A
2654 G4 f) C7 V: l, n  s
2665 O8 j/ q" N3 J3 D
267
! H6 l0 K/ \4 U268- a# Q1 j2 K- w& Z- Y0 d
2695 M% X1 ]) U. w' R: B! H' p
2708 o) C' N5 ^* A# e* G/ d
271
2 V. D4 v5 O  v! e. }" Q, L  D; l* b4 I2723 B" }$ N1 H! a, e; }7 g; g! G
273& q, K' `. L  E. X. E+ i
274
) t' B! i( z- D- N8 z275
3 `6 O& b" l! \" p$ g8 v; q276
$ i' `3 V( j4 @* _' z277; x' x" d$ a( p0 E/ ~/ w
278
/ m& _" b- t3 F/ l- N3 ?0 ?279
# s( R4 w/ `- n1 Z2802 c8 W0 q' x! s8 N4 q. d  i
281  i( Q/ p) O) q# s! M- V
282
; a, O% f7 s* @6 |! {5 g! w283
3 g0 n$ e$ P1 K# ^2 P7 V5 ~3 U284
  z# W8 e, {4 ~0 }; v8 }/ `- d& S285
' O* ~8 h. T6 h$ z! s) H2864 V$ K) e$ X; k+ S# d0 o
2873 j3 n0 }5 Z& p) h& e( }
2885 X/ j, W5 W5 K  L
289
9 d- C4 g; U8 \7 ^# I% @; j% i4 O! O2903 i$ N7 A  T* Z- J7 k8 \8 B3 G, a' R4 `
291
, u2 i; e/ K3 J/ ^. P/ W2925 s( H8 X7 j6 z/ h: B( w: r
2939 e7 }5 t7 ~# n2 L* g
2949 }$ R+ f9 q0 u! L. E' v! v
295" _- L1 ~; h8 Q2 e/ X" D
2960 e! @' y/ q7 n, I2 t& E8 A3 u8 g
2976 {  ^) E( l. l+ s& k
298
, |4 i( }( g. ^$ T4 ^  |: ~299
6 b/ a+ O# r5 O3 q300% n2 Q, n( P" @( W, p" A- D
301
3 q9 B7 D+ O+ N8 G302' O9 @0 W! c# i
303
+ E: E7 J) h8 _  Y# g& @
define('V_CACHE_FILE', 1);
/ H  n) e, z7 h- M 
6 |7 y* ], y& F) G3 @, G/**2 G4 U' Q" q9 h) J- I. @7 ~
 *@important Create the cache folder to store the cache data firstly
! h* U5 c' c3 c* v6 q ' n4 _' t8 L1 B7 B, C  Z( X
   #create memcache local cache folder
, M3 ?& J& P3 R: h- g+ L) T# f   mkdir memcache ; sudo chown nginx:nginx memcache. n6 E1 l& U& I9 V
 1 Z( G5 z7 [6 [
 */' u) \) D5 I2 \* M  u4 X
function v_cache_file_dir() {
' ?3 |, S9 S7 q$ m) a0 u# T5 e  $path = dirname($_SERVER['SCRIPT_FILENAME']);
; U  J5 v- ]/ d" l  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';* E$ n* A* s" ?8 g3 H
  $dir  = rtrim($path, '/') .'/memcache';5 A# J! N5 d& k' A( o8 p) @
 
. I! W5 U$ W: l+ L, S) @2 L3 h- m  if($_GET['debug'] == 'test-cache') {1 Y  \. |, m) Q7 Y2 H4 h
    drupal_set_message($dir. '@DIR');
% n& U" k2 k5 w/ l& S9 ^( g, p. o  D  }
  B8 I* [4 u. i7 f, J# N  if(!is_dir($dir)) {
) X4 U; y! K# N# y! e* J    #mkdir($dir);; b0 Z% R% e! b$ Y! s
    throw new Exception('Create local directory for cache, ' .$dir);
3 l/ c. t) {7 I3 T2 ?- b' _  }
8 e! L+ S8 v0 K  return $dir;! @, v- O! s7 v& _
}; a8 a. \4 V2 K/ D9 g
 4 D5 V  }4 l* v6 F
function v_cache_file_set($key, $value) {
7 ^/ T/ ^4 H! Z2 x; C  $dir = v_cache_file_dir();
6 K6 \+ U0 N; M; k# C1 s+ J2 m  $file = "$key.ser";5 T4 ~# T' A$ A* _  G$ D4 \
  if($_GET['debug'] == 'test-cache') {
' g# u# y: m. {. ^    drupal_set_message($key. '@FILE_CACHE_SET');# D# D# J6 D, I# Y& L1 x& m5 a- C
  }
* F- j1 T& l$ _5 o! t  file_put_contents($dir .'/'. $file, serialize($value));
, g/ F6 E  T6 ?6 _$ A}
$ G: @1 ]) ?* K  O " Y, ^& E. }0 v; D
function v_cache_file_get($key) {0 G: F7 f4 f1 d) u3 U9 X
  $dir = v_cache_file_dir();
/ X3 a3 C& v7 t$ v+ k  f, j! ] - [8 K8 u# M( c% b& y
  $file = "$key.ser";1 c. Y4 t0 ]2 R' A) J" x
  $file = $dir .'/'. $file;, ~/ I& |/ z1 C$ {
  if(file_exists($file)) {- y% P+ m3 o8 `+ O! G
     if($_GET['debug'] == 'test-cache') {
0 {- v$ h' A" ]* x; q) w      drupal_set_message($key.'@FILE_CACHE_GET');
3 `# ]; O/ Z8 f8 F8 H3 f  z7 P     }
" ~" C! s( M7 |+ |5 U% Z    return unserialize(file_get_contents($file));8 n5 h2 `8 e& Q/ d) v# h
  }
9 Q  D! ]) M) Q& `6 M5 u. k  else {- X7 K( b5 C% i+ _9 W
    return false;; b7 l/ A; I: `, j3 o
  }
3 D/ L. W6 s. m; v8 o+ F( p}
: H- E/ _& v4 \; m/ E/ t- [ 
3 U. K+ m4 s, j' _7 Ufunction v_cache_encode_key($key) {
/ ]' b. p2 F1 c$ O) \  $address = $_SERVER['SERVER_ADDR'];; }: K, _2 c( w4 H5 E! `
  //$key     = str_ireplace(':', '-', $key);
/ R- L" [2 C, e2 X2 |  $key = "$key:$address";
- P' Y$ a7 f9 y: c  return $key;# `/ H" L: C. K. _
}
, K7 U. R- O- K7 }# v* l2 T. H' M 
- o7 l' c$ |+ Y. Z( [function v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {
5 R+ S9 P6 a2 v& Z, P  $key_mem = v_cache_encode_key($key);: F+ Z. S( A. O$ v" S7 Z5 Q7 ?
  if (function_exists('apc_cache_info')) {. L* |: E% z( w6 a8 W
    apc_store($key, $value, 60*60);//1 hour
& a8 U) G1 _: |7 Z& D+ s    cache_set($key_mem, time(), $table, $expire);
# J' \5 r* ?! q  }9 I6 C3 Z! ?  u; D, r4 i
  else if (V_CACHE_FILE) {
6 s' M" n; ^" w, h  h$ P    v_cache_file_set($key, $value);//1 hour
1 n* [  k0 Y0 W, U; m) R$ g0 @    cache_set($key_mem, time(), $table, $expire);
: }# F4 C( e. g+ c5 o" C  }
3 _8 m2 ^3 d4 r0 j' }) r9 H2 @( w3 U  else {/ e5 r( s; N2 e; m/ g: D. w
    cache_set($key, $value, $table, $expire);7 H& ^4 @! a5 |
  }
2 A  p; H1 w! T$ \/ p# \: I}
/ K. ~& \6 j% i8 b 
: o; j$ r" }3 Q% y8 kfunction v_cache_get($key, $table = 'cache') {$ P% n1 F9 A* I1 U$ U
  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {
$ H/ t4 Q$ f2 j3 H    static $static;
8 K* Z3 e# z  U" b/ k2 f    $ret = false;
' C: e* m5 `4 x. A3 \  if (isset($static[$key])) {. g, D6 N8 n: |5 C! M0 G
    $ret = $static[$key];
1 A+ F9 @. \4 [: D, [1 n  j2 ?  }3 U) L6 N7 M$ T8 h! B: Y/ f
  else {5 H$ Q( |+ ^, B* K1 ?- [
   $key_mem   = via_cache_encode_key($key);
' B2 y+ y4 l( ?: x6 I4 J   if(cache_get($key_mem, $table)) {
& f! @  X" q! [: _$ Z8 o8 M. H     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';/ D$ }' G2 D, |# r, f! [; e  m7 C
     $value = $cache_callback($key);: y9 Y+ `  I. q6 t0 N: F
     if($value) {
6 ~1 @1 B2 q/ ~       $cache = new stdClass;
6 a$ O6 G4 |5 x. E% V       $cache->data = $value;. o0 A9 v1 E8 @5 ~
       $static[$key] = $cache;
6 a9 l4 ~' d8 d; c; ]4 u       $ret = $cache;2 i; S5 P( B! A2 w3 o
     }
& b) N! _0 U$ u1 X% \   }
, ]" V& R1 z" V9 d2 t. s  }: e/ k* R/ l0 o: B- }. x: T7 F
  return $ret;; }. i% J5 L$ m
 }
) w3 X! u" t+ M- [6 ?; Z else {  z( S( e* Q+ U
   return cache_get($key, $table);
* c+ |3 ~% Y' z- D/ Q  }
9 g. O8 K5 M! H}7 f) H' F0 q; u, }4 O
 
9 C- g  t& b5 R$ c0 hfunction v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
7 p5 j, Z8 M, X; a7 O! F4 j# \  if ($cid) {
# W5 r* G6 b3 N+ E' @" v: }    cache_clear_all($cid, 'cache', TRUE);
  d9 W& I6 D7 A  K! O1 z    //apc_clear_cache('user');
% O6 y% L8 B6 M6 {% {+ w  }$ X" h- i9 W8 p8 ?6 u  @' e
}

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

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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