国外设计欣赏网站 - 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
* W. N" H8 o% x+ O" q. Z& a4 C201' r1 x4 \* ?8 m4 y
2026 |$ c9 _0 [$ i. }4 V
203
  M( \, A2 H7 l  ^$ V8 [$ H204) r0 \. r' u6 c
2052 O4 m1 r# J0 D: V4 ~
206
4 V/ T$ z8 a- a0 ?4 z3 j# @2071 b. G7 ]; ^2 {. O- |5 [& }1 R, s
208
, i9 G0 E! C1 A  J) `; P% L209
: D( s* Z- i' H& ]/ h210
6 w( `$ P. G( I' \7 ^211
4 J2 D# t& A. k" j212" k; Y3 v2 k% g! S7 s9 O( Y
213
4 u3 K# a5 v9 k214
& S3 z  a) m( M8 n; u# \( f6 _215
$ M+ a. E6 X0 G' u  U& M216
% J) ?# S2 t; _' z& N7 G8 {217
  Q. E& Z0 T) ^8 v' @- n7 h/ e, x218
2 U8 Q$ |, b) `, t8 c; c6 K219% a% T3 |6 f# A! p, x6 O
2200 v) I) u2 s, s$ ~+ q3 O
221
  u* u4 ]) Y# ]6 u) G" z" f$ q222
1 q+ S: `: M3 {, J+ ?+ ]223
5 Z6 h# R/ @' W. q' H/ T; t  v" {7 _' h" g224
# J) e2 ?( Y2 x1 [7 G& r0 b8 h225
% \% p9 _- z$ _! S- ]226
6 S) H% f, X2 M  A227
2 `  z! p+ D1 y- R% A+ H5 H2286 a3 P/ k. b# f% w
229
# t2 G, @! m9 |0 `5 K+ U$ P2 I230+ O9 T! x. ?$ z6 V) f2 X0 ^
231
9 @9 d; E9 N# L; |( p% W$ Q232
# t1 j5 R+ o8 K# P0 c; F233  H! F1 O0 }( P, X" v
234
, n8 J) z" m; G+ K1 p7 @7 i235) }" d2 C/ }, }/ K
236  t; P: x5 `9 }/ d+ k! x
237
- r# q, ?4 T. f5 D238
; D) D/ L- u/ e239: {, D# p/ |; ~: i. Y7 c' x
240
8 ~+ s; Y  {0 i241
0 X' p, O! `3 W4 a0 Y( \4 x- O5 {242+ W0 T) Z) p/ ~+ h# d+ w
2438 N  h& e# O8 [- B1 B5 r8 ?. q2 \
244
; A- t% d- Y# n7 V245
$ I# v  o8 M" l8 T+ v' n$ j* i246' x4 W) M1 `3 K" [% E
247
* p1 g2 J$ x- ?% @2 P+ t2481 a& K3 o2 l0 U  D# ~0 B& R
249) K" j' B& z  u/ z
250
+ K; p$ W% m" d251
. d- S% T, [- |+ Q252
5 D* b( n: b; y5 K! }' A253
; W# y( y0 z+ ~( m" O" M/ Q) u- r254
3 z( P* `/ m: K& b255
- o5 f; W  @6 _4 E% ^2 _256
- \8 }+ i8 l, @4 q+ z" I. V" v257
& @0 Z0 ?$ f' ~: V! o6 K9 a8 J8 d258
! ]0 S$ G; ?) C& z259
( [. M/ O  Q& Z! @0 ~260# @- l( z- K% M+ r7 f. B& ?% O$ ~
261
4 ^3 v& g8 _( R3 k% T+ x+ P262
! U9 d* ?, \9 d. Z263
; b* g) a5 N" D  W4 Z& t# ]264
/ c+ l6 Z6 D% O$ M! o# K6 a265
2 t# l+ E% D7 u- K/ h266
# [, q9 V' h! |6 a267
# W3 _. G% D8 G3 H8 F+ K" i- m2681 @% U$ U" s, @1 U$ ^
269
1 M: d( x$ B; ~  i( C270
7 @0 X( h7 ]" B. M4 X$ J271
: ^( G- _) Y! X2 R: R2 S272
! \8 O  ?' J7 w' `; u1 E273  u. C% P$ c. G- I5 k% J, f- S, m
274
; v- J& a8 I3 [4 E275
4 x1 N: W, I6 P' z3 W. I+ k  c1 k: V276: [0 |3 d$ c! g
277
( g. }! `* K! R! E, u4 a278  E3 {! U+ I, r1 i' o7 u  `) v, b0 F
279; D) q% m0 y& x* t* [) d
280
8 g9 r: K6 ^( v5 n9 m281
) w6 O# n' a* i1 X& \  ^9 z282% U' M( S6 \  A3 A
283  ]. `, g5 n6 M. U. B
2843 S6 h1 j8 F) v+ ^, Y0 H( n2 W( y
285
( t1 }4 B9 i8 b286
7 i# X# G1 ?1 i287
4 t2 H9 A+ l& ~% u, F288& |' V% k3 M+ _, b) B5 o8 b
289
" B: d1 F5 u9 }2 K- b8 m6 y2901 D/ n. J$ y+ g' R( c1 G/ V' E0 R
291
' m' ^/ O/ E1 N! O* L292
" x$ ]4 r. z1 r2 |7 s# {2934 |, o, A" k. d" S3 H% o) |
294
# Z* j. Y+ _- a0 T+ z295; @5 i1 j* W; R/ X+ A' w& b
296. t, ]6 ]% Y4 x) \- O
297' Q4 B: r1 w8 z% o7 I( v
298
) @$ Q: J- n$ T& ^5 R299. t" o# L5 z' F+ ~& }. O) W+ `) h" g) k
300& ?9 Z& s3 R& K& S
301
9 h0 q( `% _2 b/ I3 s8 w: I: h302
4 ?% |" G" g% ?5 u" [3 ?303" \( K/ n* d/ L: C: O
define('V_CACHE_FILE', 1);, v3 R# F. a6 C
 
. {# I' r3 w* u( S( B/**
9 D+ L% V6 b# p" [% w) _ *@important Create the cache folder to store the cache data firstly2 X* Z" f# Y3 N1 k" a
 % _) r5 w# P8 ^- U# u! s( A- @
   #create memcache local cache folder
) f4 m' S: q  a   mkdir memcache ; sudo chown nginx:nginx memcache# Z  ?7 X; E7 Q- b7 b
 
+ t/ ^" W' U7 }: Z& q; s9 Z7 \) w */& q) h6 u& O% U/ |* q
function v_cache_file_dir() {
1 E7 U* G' r  Y  $path = dirname($_SERVER['SCRIPT_FILENAME']);1 m. a2 X* G" K6 |( i% g2 j9 U& J
  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';! K; }$ S: X8 z3 q7 Z  S2 J4 x2 v
  $dir  = rtrim($path, '/') .'/memcache';
; W9 |; A* o; L; D! v 
2 ]# }7 P+ k0 Z4 T* M- O- C. Z  if($_GET['debug'] == 'test-cache') {) p8 b$ K+ W' y
    drupal_set_message($dir. '@DIR');& U0 V3 {$ _( b0 H5 i: A
  }$ T+ D6 L$ _. _  C1 ~% J
  if(!is_dir($dir)) {7 ?" D" B9 n0 T. l+ Z
    #mkdir($dir);
" Y! k9 z( j% r- m% y+ R# V7 r    throw new Exception('Create local directory for cache, ' .$dir);# }8 ]2 W! A3 h4 |
  }
" h0 T# }3 l8 t  return $dir;$ H2 }- S7 _) f0 w4 F& k+ u
}! o: ]" ?" ?8 s2 W, u2 x5 h# I
 8 e9 j, s0 A' v- P! S+ n
function v_cache_file_set($key, $value) {
4 n5 I: g% L2 v* q. ?  $dir = v_cache_file_dir();  s, Q% x3 S! d& {; k6 x
  $file = "$key.ser";
: l/ R4 s7 r3 A- f" p1 X  if($_GET['debug'] == 'test-cache') {
/ l; P4 n. ?* A, e+ K    drupal_set_message($key. '@FILE_CACHE_SET');
+ g; J* Y2 B; C) c: y. s6 u9 M  }& y$ s9 Z/ ^! X( h3 G8 }" W0 S
  file_put_contents($dir .'/'. $file, serialize($value));
' ~8 W+ I4 C0 \  h}# c5 o% H0 y! o. M/ s
 ; |3 `! j& D8 r$ A0 j3 a6 x; b- n
function v_cache_file_get($key) {
- g; L4 x) d- `4 e( l* V  $dir = v_cache_file_dir();
3 h$ s# F; o3 P7 v6 N. x3 \% o; r9 R 9 {& [5 _+ W/ ?4 Q% ~% n
  $file = "$key.ser";
4 Q* K! c- Y* a3 Y  g4 r  $file = $dir .'/'. $file;5 n1 W: h$ o* g4 a  c4 r3 t( n
  if(file_exists($file)) {
# ~& k0 s3 \" C: G. Z. b( f1 q4 x     if($_GET['debug'] == 'test-cache') {
* e% p( b1 h6 R8 f- z  B      drupal_set_message($key.'@FILE_CACHE_GET');
# |" \0 h! A. L. L. j% L" J1 S     }8 e% [7 l9 `8 `: b2 W
    return unserialize(file_get_contents($file));  Y3 f8 ~. V5 o$ W  q% u
  }
5 U# i/ F3 u1 |/ [" [5 Y- V; E  else {
/ n- F0 V) h0 e! {8 @    return false;
3 I( ^" ?- G/ y. n7 m+ H9 N  }
( x& d) M* s" D/ }2 k) `; l4 P" }}) ^) n+ L- O8 G& d5 O6 W* S2 N
 
0 O. b3 j* O2 M; z4 r9 E" d' N5 ufunction v_cache_encode_key($key) {( u. j4 Q) j  ~! o
  $address = $_SERVER['SERVER_ADDR'];
) ?1 i: A0 l- b2 z  //$key     = str_ireplace(':', '-', $key);
: L7 y' y# R5 s: w7 {: p) e  $key = "$key:$address";, b5 t0 L  y( w+ L+ ?* ~% J
  return $key;) T5 o; I' }) d+ q# E( m! r
}
& a4 H: S0 E2 E8 o0 F2 n' a% ? 
. D& a  s( J& f8 [# S; Y: F9 u; Nfunction v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {! \8 l5 x3 V4 V
  $key_mem = v_cache_encode_key($key);
9 Q7 {& i) z9 w  if (function_exists('apc_cache_info')) {
7 j) p8 V9 Y$ Y2 M+ |6 a! s+ P. r1 v    apc_store($key, $value, 60*60);//1 hour9 _/ @' B# n/ \8 F, P, |+ a  D
    cache_set($key_mem, time(), $table, $expire);
& O' \! }. ~) |* K! r! S5 j  }
' q7 r. h" h& s; e4 S. T  else if (V_CACHE_FILE) {
2 N9 a( r: e! I  a4 V( A    v_cache_file_set($key, $value);//1 hour2 c9 O7 O& L3 d* a6 J
    cache_set($key_mem, time(), $table, $expire);
. g6 ]( |0 L- [1 @  N1 H" S  }
; ?8 C, q% Y- B6 U" n. s  else {4 F" l2 R+ O3 ^$ G
    cache_set($key, $value, $table, $expire);8 S( O+ g* N( b5 c% j2 h
  }( q: [5 @% H& Z
}* c# d( v7 C* F* a7 ~2 K+ K
 
6 Z: R: }# s, m& m. g* ^. rfunction v_cache_get($key, $table = 'cache') {
$ V* p* G. n3 G) U3 ]) B  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {" f1 E7 U# Q+ X1 m8 `
    static $static;
% ?) E+ [9 U' i6 b- J6 H8 d$ ~    $ret = false;
& q7 q  U/ U  R  if (isset($static[$key])) {! R& H' K5 N5 l- M" O& t4 y; h
    $ret = $static[$key];
4 C; J2 \! d9 v, X# I  b$ Q, w  }
, E3 }1 p% w4 x) ?3 s  else {. Q% m- W# E; q- f! R; }
   $key_mem   = via_cache_encode_key($key);! a8 ^- y3 T) h
   if(cache_get($key_mem, $table)) {
+ g: ?; P& B, s/ @- z& c/ r     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';9 `- v  V: Z' Z4 T- i7 L% G+ ~
     $value = $cache_callback($key);
$ K4 ]* E* {8 ]4 n0 Y! y! d     if($value) {
" c- d( |4 k# m( |       $cache = new stdClass;
8 H- t1 g$ g% T9 U       $cache->data = $value;: S* t/ J8 g- H5 S4 A+ F
       $static[$key] = $cache;
# }, [/ c+ p5 I! _  _7 L/ X       $ret = $cache;
8 N1 Q) N1 Q' I3 D     }
) l4 a0 v5 M/ @1 C: ^( \; j   }
) I2 U, T7 O0 P4 {5 A  }/ o# h9 W# [. n1 a
  return $ret;
/ j2 Y! w' B$ i5 h }- W" K* j! C, F0 ~* U7 g
 else {  P; t1 C  b0 O$ Q+ M- m; u9 P
   return cache_get($key, $table);
% f; ?1 a* @' E) w5 j! J. a  }
, |6 W2 P) n/ @* y7 [2 l2 \$ R$ i}- @! n6 @; a, \2 n( ]; L% d" `7 X
 0 _" P% F! _* L+ x+ V
function v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
7 A! _0 A% f, D) w5 O8 g9 I  if ($cid) {3 j/ K! p6 a5 F2 ^
    cache_clear_all($cid, 'cache', TRUE);
. I- }- X( Q. M) x4 s6 j6 Z    //apc_clear_cache('user');( d% }/ Y( e% }, p
  }, g- R8 H, U, \8 ]; d
}

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

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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