国外设计欣赏网站 - 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
- @/ c$ h& p2 O8 h' s" v201
* m7 u+ h6 `5 r8 Y" e202
# l/ i) B! f- d5 \203  |9 I/ K2 h; ]) k
204
) d2 r9 j3 k1 m205- h9 r; n+ B! e# U. V. [, p1 i
206
$ ?- H$ Q. v0 V2 C& j5 G6 e* W/ C207
& u4 [1 E& k( T2088 t9 d5 Y4 k" {! p9 g
209
: j* i% _3 r% x. a, F0 t, l210
" k+ {0 J: y4 Z" I9 x, V211' N9 Y# w' L: G( |
212
  W, Z4 e2 ?# ?3 {) D( T+ _213
" z% b$ T/ r( a# A$ d0 \214
2 y; h9 H6 j. N5 o" X) X215
; E4 l/ m7 \) V9 J) G6 t# S216: X6 F0 z  s' v& y2 j) @3 \1 T
2179 D6 L6 ?8 s& c5 S; J# L! |
2186 _8 T" a7 z! U6 w- c& E
219
% z/ L* \! P+ E, [" w& A  w( B- g220
, X4 z0 ~- Z# x# i221
- N3 I7 \# r8 |3 a2 Y* j! v222
) i6 g4 y( \% w" W# D+ U2 S223% E7 X3 [" A% I0 L. ]2 P  v
224
" p- k% R' g. l5 ~5 b8 W. f225
: U9 M. I1 i% h: s8 a  @. r226
0 c: G+ d  ~# h5 d) ]0 S227
) C" o5 F/ v* g6 \5 k: @( T9 q& N& ^228
0 D& Y4 @3 C' L" b. w229
( h: h- G0 L" I0 }3 D& `0 n* A' t230( I( H* b/ J6 u; l) F
231
, I1 W+ K& s, l2 D: |; E0 M8 h232
- P/ @$ F5 K9 c/ t, Y9 ], a; \1 k# q233! |: M  J2 R' I4 Y! P) S
234* ^2 D+ |* l- [+ ]* S
235
/ }4 T% d" D. P: p% [- z236
. W; C, L! L6 D6 U237
  |2 C' j; p4 W; m  |' w$ U6 d238
: R/ k5 h6 O: ~) ?: n% q' ]2396 C- U" u( w0 ]4 z" u( @+ w
240
: t" c7 F: f1 B: ~" z/ ]: ~241
3 T$ Z* Y: A  a: L/ l4 {3 Q, |242! [! A  K. V& U
243
2 g9 _; o* g6 T3 j1 G; p244
) |1 u6 E6 K4 J. E& N245
+ P8 g( P0 T* v2 M3 ?246, \5 G7 T% A1 ^
2477 t. I9 A. i' \7 ^: S- ]$ A
248. [4 S+ O+ j. T4 g+ p
249
1 T  M) i+ n6 B$ w/ T+ x* \# U250
  Z2 g* U7 t% u* ]( W% Z251
' r6 k4 X( P' H% @4 u252
9 O$ M9 Y8 l, T; K7 U+ S253
9 n2 x1 h0 _; Y: @254
4 q! u8 V$ ^7 b255; e9 Q! Z0 D: S, {$ N
256
8 i1 _- y% _( P257# x+ r0 U1 P% y8 A- b
258* C0 C+ R" a3 i
259
: M5 ^0 [  H2 d9 B! q2608 x' p8 F: A7 @* y
261
4 d# ^2 p1 ?+ H' G: j: u262  \, }) v( p: L) I* o- V2 E' e
263
* |5 S, O) s8 |& a4 N: H3 n' o264
1 T! b& ~& l/ ~  i& f& Y265
4 g1 b6 y1 O5 j# R2665 z+ o( K: x+ i7 [: O- N- \
267
" ~6 B( ]+ Y  j% v- g$ b) D6 j# y. k268
$ c. ~1 o# g8 U0 @269
, Y9 ?  P' v5 y, @! f270
+ E% `. m2 C" f2 X' U271# i3 }& O8 u9 x7 o, u3 ]# G
2729 C) Z/ X/ o3 J( @, Y
273/ f1 s( K8 T: a( P* C  W
274
; U' y$ T9 e& v3 B7 t275
* b. R  M, j0 l  w+ Q. [276
% G$ d, Q5 j1 T9 v( g5 Y4 X( U277( d# `& K8 q3 `6 a0 h1 E
278% S9 h- q" O3 b0 M  m4 @
279
4 W( E; M0 E5 g! ~4 |* A8 g2800 Y- c- ?3 ^4 x( z7 ]; M7 k
281& G0 E# |7 r5 H+ y8 \" o: d3 C) Y
282
* r% ~! N2 z* F9 Q+ P# w283
- H0 Q+ i; {7 Q+ x6 d+ S( o8 q- M; w$ z2844 W( s3 Q4 I0 Z0 O5 r! ?2 p5 k
285
% b1 W$ O0 E* v+ [286
  B& [9 x" t% r0 X7 o; j287) V& U" Z2 ~& l
288
4 D: D% T. d6 N' w5 R- v# V3 P289* f1 o! X4 w+ [
290
" ]7 ^/ H  ^- O( {" l  ~$ n8 Z2 F291
& X' G+ y1 \1 y8 ^292, U0 L+ E. f8 }* @( m
293
" z: w% e' j0 c6 W( g294- F9 d! u+ R& n9 I
295. H" \" b; g3 Q8 |* n! H
296
! [6 }% N  \  C" ^297
% V* |% x1 T# d3 a; {' e298
6 d% u6 k9 J" W1 m- Q3 Q/ \299
: N1 I8 b9 x5 k5 p& c300
. s, [' G4 d$ _3018 k* \- z: k/ w# \) }$ o. g+ c( ]
302
( ?, r6 l  \# w303
9 y# e6 d& s  Q* e. `
define('V_CACHE_FILE', 1);5 v2 p2 ~; k' h/ F. W2 Y/ r
 4 }! r. b' a3 I
/**
- i/ U: ?  J6 M, @ *@important Create the cache folder to store the cache data firstly. z9 }; @; ^5 u# q+ F( K
 
* c! B0 ^9 l0 L0 e4 d   #create memcache local cache folder7 o4 _( A5 g5 P- Y% X" Q
   mkdir memcache ; sudo chown nginx:nginx memcache
! K! B# ^1 l5 J# _8 A8 [ 
8 W& O' |, g9 i: o) T8 M */
8 r$ i$ J6 _2 z8 Ofunction v_cache_file_dir() {
5 D1 F# E( o$ l& ^  $path = dirname($_SERVER['SCRIPT_FILENAME']);( a, R6 S" E( L8 l0 a7 Y
  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';
* j4 T0 n) I/ |" M1 e$ r1 K  $dir  = rtrim($path, '/') .'/memcache';% c3 E3 o1 m# h' d) h9 n" m
 
- c3 W4 s! f( [7 |) i  if($_GET['debug'] == 'test-cache') {. S7 n  c& ?4 R  G! _1 t
    drupal_set_message($dir. '@DIR');' W3 |8 B5 d/ s4 E
  }
. w) a/ v) g# h" U- |/ ~4 e  if(!is_dir($dir)) {
5 J* J: n7 G* ]* r* G# i    #mkdir($dir);( t8 g% ]7 ]6 H5 Z9 I9 F% [
    throw new Exception('Create local directory for cache, ' .$dir);
. Q5 a# N8 x6 \/ o; B# D  }! v3 {" F  H! ^! H2 i& E. z
  return $dir;
4 f. L& S$ t7 k8 j3 D* ?5 s# q}
* Y& P4 [$ |6 }) C6 w4 G 
  J0 B5 l; b! _+ L0 ifunction v_cache_file_set($key, $value) {( }+ c2 v2 ]" f* w, C8 s  {5 I* t
  $dir = v_cache_file_dir();
8 i, ?+ L' H( A/ d7 o6 G0 @  $file = "$key.ser";1 I1 |0 n4 C5 C1 n, ?' _
  if($_GET['debug'] == 'test-cache') {; R4 q( F  W$ B! L' C$ j
    drupal_set_message($key. '@FILE_CACHE_SET');/ {  C, r+ x5 c+ z7 R0 N# s
  }
' i) M; P3 p( a" }* x  {% }! _  file_put_contents($dir .'/'. $file, serialize($value));$ J6 \* O# E, M9 Z& N
}! d' H  m2 w8 a: j% P0 ~5 `
 
9 D4 `( L, i5 \9 W  R, ufunction v_cache_file_get($key) {
) c& U1 _' g8 P4 ^7 s. P  $dir = v_cache_file_dir();
4 M+ [4 f- K1 O7 Q' V" ^ 
( k; H* E1 K5 Z, K2 \  R6 w  $file = "$key.ser";# J9 K9 f/ u' a  E1 @" j
  $file = $dir .'/'. $file;* R3 _% L1 e7 h1 r: f1 s: S: k
  if(file_exists($file)) {# u6 a- k0 R  A7 m! p: z5 `7 l$ R
     if($_GET['debug'] == 'test-cache') {! Z) |6 [! J# v( R) w) s. {4 V4 Q
      drupal_set_message($key.'@FILE_CACHE_GET');9 F* ?& W- J# F
     }- n5 ]% \; i- C
    return unserialize(file_get_contents($file));( D: I/ f# f5 ~7 k* ?4 i
  }1 [0 ~& J# s  r7 G' a0 ~! l
  else {) d1 a3 e5 m4 `* q
    return false;
) H; b) X" T& u8 L: o* z. I# l  }3 W7 l1 }) Z: j& c. ^% K4 g$ C$ z
}
, p) A( ]* f# o) B ) O) B. S# j# d$ }1 R0 K1 f) y
function v_cache_encode_key($key) {; ?; l6 C  V# B) b* r7 z
  $address = $_SERVER['SERVER_ADDR'];
2 W) d, |& ?' f  //$key     = str_ireplace(':', '-', $key);  L- `9 ?, \  Q# V
  $key = "$key:$address";6 r" u* N6 b8 ^
  return $key;
" @+ \% ^: p1 y( T7 E- x2 H5 y}8 z$ a! l; L$ r
 ) u) }, b5 J/ d7 [5 q
function v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {2 K" D3 V0 X2 c5 S0 x  o
  $key_mem = v_cache_encode_key($key);
% K* j& B: m: z" }" z0 b& ]  if (function_exists('apc_cache_info')) {
, |5 ^; r" L0 u2 \# O- w" {    apc_store($key, $value, 60*60);//1 hour
8 W, _. D. U3 T* _, w' ]/ U' e    cache_set($key_mem, time(), $table, $expire);+ ~; _7 U6 J, V, S0 ~7 z; K
  }( p2 ~* c8 g- \7 a* t
  else if (V_CACHE_FILE) {
5 g* R4 k. a7 |    v_cache_file_set($key, $value);//1 hour- y# Z; X3 a: ^1 k; E/ U% ~6 |
    cache_set($key_mem, time(), $table, $expire);
' I* B/ H& T6 v; v; n  }3 I: J  \2 [% U- A2 j
  else {. L' i6 C0 z1 W  E5 X* g
    cache_set($key, $value, $table, $expire);
( p8 P  d7 T7 a3 y- L  }5 h! f8 i6 m) H+ _
}
. f' l8 j( m# K1 x9 R& e 
: I9 P9 x. E9 Z- Lfunction v_cache_get($key, $table = 'cache') {
7 Q6 w; C8 x# s$ D/ r* ~  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {9 i- @/ U1 s6 E9 N% P
    static $static;
4 q& F. J" C' Z    $ret = false;. x( z% V) K6 s" z& m- C
  if (isset($static[$key])) {
; ]8 h. x" G& w. y) _! ^    $ret = $static[$key];
6 D& }( T4 Q7 X  }: `2 F" ~% b/ p+ p3 [  \
  else {1 r+ Z* U! b0 D3 F
   $key_mem   = via_cache_encode_key($key);& t2 Z* L1 D, e9 }6 }4 w
   if(cache_get($key_mem, $table)) {
9 s5 U  s) w1 [" C9 G2 R     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';6 h1 C, U- b) r* N8 T
     $value = $cache_callback($key);
) U' b) {. a+ ?( Q5 E8 N! e     if($value) {
* z$ l* `* I( ~* R0 d: }, z' o       $cache = new stdClass;
5 S  ~8 I; A- @" V! n       $cache->data = $value;% k" s; r5 B3 M. C) Y
       $static[$key] = $cache;
# s* t& O; t4 n) w       $ret = $cache;
3 [5 _  |4 {; E     }2 C, k1 I( F- k2 d2 Y% z0 [
   }
. u/ K3 `/ s1 R  }3 t1 F  N+ p, y1 s# m, X
  return $ret;/ W; |( f2 i2 g, P/ V
 }
1 W$ F3 J, r3 Y9 m3 G else {! ~' j9 R; Y0 d: U1 G" X
   return cache_get($key, $table);
' o1 V+ n" ^+ |$ O( H! z" c: J3 s  }6 `& e9 k) G* h8 m9 x
}6 F# e% z& c: |! A' |* j# ~8 M$ i
 
/ X3 o+ ~% L7 m& ~! H9 ^9 rfunction v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
: b, g$ [& H2 O: n) h  if ($cid) {
: z$ w* ~0 V( G% i+ L; [    cache_clear_all($cid, 'cache', TRUE);  I* }, t, r  _) m; j
    //apc_clear_cache('user');
1 f: i# f1 f1 U+ _9 h. y  }; A& X3 h4 F. M7 t7 H
}

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

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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