国外设计欣赏网站 - 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
8 b8 |8 R4 v9 a; f0 ]- u201
. r% K1 s0 D& P! G  F202; o* Z3 j% v( z; L$ A
203( @9 W, ?  P4 D" U: B" j
204
2 B0 H$ n4 \2 E205& x, N. F6 z& W% H
206
9 @5 a! D' C" ?  A207* H+ {% N* Q$ |  b# Y0 `3 `+ h
208
! t! b# @" U" V8 e- r209( G& N) h. |: ~  c' P: O/ }
2109 e1 W" y# C$ Z6 m9 G* z
211. J- n/ V7 }3 b& D* c
212
3 B3 e6 B8 f, g# F1 ~# `' `9 W213
" l9 y" y0 F) m, P) n7 L214
! K! X) V& |! F- v" N0 W8 F215
3 _- f' x& Y4 A8 {, Y& ?+ ^4 G216
. Z! N5 `2 q4 k: T6 b217
3 b+ ]" Z+ V6 k2 {- r  V2 T0 k218
4 m- P* `7 X; P) D* M) n2190 F7 N7 O+ m, s) t; I7 e
220! x, r. T! L+ ?6 R. I" C: S8 [) b
221
# Y1 C8 K& j9 A9 _222
: D  V& T2 I: K2234 B4 s2 b! l8 Z8 C
224; }% v* c, g6 F! j4 J+ B
225
. w+ j; r+ |) X# m) O8 I2268 j* C5 c" @! j8 g
227! X. f/ Z6 h- @' d
228$ U* c7 ?/ d  p1 k) r4 p& @
229
8 [: t1 v; J( E  d3 o* G230* I& Q' G' Y6 @6 G5 c( }+ ?
2317 j7 E; T% T: E
232
/ o1 B5 G$ _5 v* w9 ~233# H7 V% e4 u9 n* a* J
234
2 k/ Y. v& e+ W& g6 A! p% r  x$ a235  D: e. Z/ h- O
236
8 M3 r  }( H6 l4 Y! l237  x1 A: }( }. Q# q5 ^
238
5 b; l3 i/ _6 ]3 t& p) H239
9 C/ ~) N; P. i: G2406 |* S  ~6 B3 M1 C/ ^8 l7 x( d
241
" n- x9 c' R9 I242# h) U6 m! j' m- H1 m' \
243
; a! u9 ?6 T+ _5 B6 t244
9 I2 ]$ L6 J$ U7 n245
! A9 K1 j+ C2 {% W246
7 X, B+ }" G$ `9 f+ p/ u5 E247. U: m$ g5 j* i- \! Z* ~/ `1 J2 H
2481 d2 f) [% B: N4 q$ D& }" b' T
249# U& u4 R1 v6 Q. `7 ]/ V7 m
250
2 k( X" i5 Y# ?  y251
( q% m4 Z/ _9 `9 g5 u$ i) A252
- ~, H: T$ ?! W$ b253- W1 U) q7 ]3 w  X  y, [" J
254+ P6 Q# s  D3 g% w
255$ x0 D. r' s: F7 ~: x
256
0 A2 ?/ P% d. B257
' h) V8 S6 h  Y4 K9 p$ f2582 i6 m% @3 |" v/ h/ i. V: J
2593 j: W' n4 {6 L& j' p9 a
260
# Z' J& P$ Z, W- b) d" G+ M' B7 t2614 t5 @: c) F7 N2 |2 F
262
) W1 c3 ~$ b: v) V& g3 P5 ]263( a7 M. T& _  }' _
264/ C$ k# \$ t5 R6 @( `+ k
265
# @1 b  x" f/ ?* c266
2 X  c8 Q0 I0 x5 |! e267* r+ _( k/ D1 B( D* P
268
# A7 V& ^+ {: D  q269  f/ G+ U7 K. p5 @. I# |& n1 \
270
+ L( a8 r" K# I; q$ O2 g" p271
/ P' D  K& w+ b3 D! S2 K2721 }8 u; k' N$ ~7 i/ Y- ~
273* S3 ~/ N  o) U) p
2745 y6 h" B) M/ g9 o) o
275
" R' i" h* T" I! o0 n& \% P2760 o, g4 ~% v6 ^
277  Z' F7 n2 w9 j5 F2 |1 ~
2782 D' D8 ]# z  a& U! ?
279
5 F6 y- B" f/ r* |1 T/ E280
4 s( }" E0 ^% a; l/ ^281
" n- c' q- r+ `- D9 U8 v282
9 G; ^, r. U" h4 Q* z6 Z283
# J9 H: N* ^( e! g284* \$ ?% C- ?0 t
2853 T1 o& `9 N  R: s& f
286
2 M2 y" G3 ]* {6 Z! {; G9 @+ u287
2 Y0 |& B: S( x+ Z3 C288
; `# d1 J3 r- s$ q+ J2899 g3 F4 C5 r, M9 h4 F1 n
290( R; N# p2 ~- ?
291) y. ~3 x& f! ]* [
292
4 b4 H' R# B4 e% X4 a293
" V2 H4 t0 X9 I% X) ^294
9 P! ?! r9 M5 P. @6 F295
+ f/ L, N6 v/ z# b" k. `* e296
2 d: p# D0 ^9 Q& _$ u! Z2974 [0 i0 }, s, l
298
- u/ S6 a" I& H# {299& z- P& U& c. G
300
; K! n1 V4 s  A5 q% F2 n301
7 @- z' m  F3 n4 h! T4 E302, }' U/ P! Z( O. Z5 _
303
, }- ~4 V6 {7 m$ W1 e
define('V_CACHE_FILE', 1);9 {' g, e% ~( H$ w5 t8 J
 4 @  J* m8 |8 b# I. h* o2 @
/**
9 f; Q& A' Z6 }% z* i$ T *@important Create the cache folder to store the cache data firstly
8 |0 V5 y# F! `% W$ }" c 
- c, f8 ~9 A" E+ D! E5 `$ o   #create memcache local cache folder* i2 T( Y& ^, Q6 U0 y2 w
   mkdir memcache ; sudo chown nginx:nginx memcache% f2 W* c& ?3 Z# Y
 
6 m, G/ j1 W- S5 V */3 @! Q4 y5 [( G/ \
function v_cache_file_dir() {7 Q" @0 p2 _2 I0 s2 z. {
  $path = dirname($_SERVER['SCRIPT_FILENAME']);3 F! g, P: t5 s7 q; \
  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';. ?# r8 [5 c* [! o
  $dir  = rtrim($path, '/') .'/memcache';6 J* a+ {% |! s1 F1 T  f, J
 
/ _3 G8 ?, }. _/ h  if($_GET['debug'] == 'test-cache') {
) z& V0 ]+ _# L    drupal_set_message($dir. '@DIR');
. l7 Q* l7 c8 a5 n6 M3 a" G: n  }7 }5 M0 S4 j3 G" f. P* y/ D- }5 a
  if(!is_dir($dir)) {: ?( G+ Q6 X8 X- @$ u
    #mkdir($dir);
% [5 s6 ?8 U' @9 g" R# g    throw new Exception('Create local directory for cache, ' .$dir);5 j2 `4 T$ M( |) N& Q# W
  }
6 G9 ]  `$ w. [5 H4 N) m' S4 U  return $dir;
2 ]% d, e9 S& }* ~}& O/ ?9 a: @: Y3 f7 n! N8 _# T) B
 
+ \; \' @- b( Wfunction v_cache_file_set($key, $value) {
" u* _3 Q, k$ k" W9 I+ X3 R  $dir = v_cache_file_dir();
2 j- x8 \' r1 @  $file = "$key.ser";3 x7 N7 S0 W- d- y* s+ X5 b5 N
  if($_GET['debug'] == 'test-cache') {, t3 c4 ~3 W( ^1 F" U. T2 _
    drupal_set_message($key. '@FILE_CACHE_SET');
; y2 l. j+ x! g; [  }. r( e8 t( \4 \: r+ Y
  file_put_contents($dir .'/'. $file, serialize($value));
! Y6 Q: U" N0 \- u6 {}4 _2 r  d  ~) r1 K  G) f' ^; P
 
: I! c( T9 [. ~  |4 x5 f' Nfunction v_cache_file_get($key) {
$ J- d5 j( A' U+ l# _  $dir = v_cache_file_dir();
+ \2 f& d; O$ o5 O $ ~+ Y7 R( {; o7 h( a, y
  $file = "$key.ser";
! Y0 `5 @& J; v5 Y3 |5 q! K/ L  $file = $dir .'/'. $file;! S5 ^( c; A" `! c" u: x2 H
  if(file_exists($file)) {
  A: K  g7 S4 D. G     if($_GET['debug'] == 'test-cache') {
) ~( O" d; B! s  i! ?2 g0 j* |      drupal_set_message($key.'@FILE_CACHE_GET');4 K9 u( i8 C! r. D3 U, K' p
     }
" x) i; w9 D/ ~7 h' M9 n% V    return unserialize(file_get_contents($file));
, n; J3 b8 ^2 m5 q. T: x* B  }
/ d9 h$ z& B+ @+ ~5 u  else {
; h) @% |0 \& e9 e$ B6 i' D  ^; h    return false;
; \+ H- l2 d$ h& l5 K6 G% i  }
- V' h% ]7 T" R' d$ b}7 P) s3 T9 O4 A' P  n  L
 
* x& o! i' f+ V. ffunction v_cache_encode_key($key) {$ ]* I5 k5 t" [8 `9 B
  $address = $_SERVER['SERVER_ADDR'];6 q( J. c- H; F; k& J
  //$key     = str_ireplace(':', '-', $key);# O4 }% M2 u9 V& }1 m
  $key = "$key:$address";
% L$ s# A- R: G* O. G  return $key;
% M1 G+ A% W5 K0 Z( w$ q}
! p% Q5 H' {& \; o/ y + V+ {/ \+ U4 F1 Q& p% {% N
function v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {
! N7 n! C3 Q4 ]. m8 [  $key_mem = v_cache_encode_key($key);
& P; W* g4 U" I  }: }  if (function_exists('apc_cache_info')) {
% k* n" B" m6 u* O% }* ~    apc_store($key, $value, 60*60);//1 hour& S! s; F% J' o$ ?
    cache_set($key_mem, time(), $table, $expire);; Z* r+ _: _# B- a/ r( r% q7 U; W/ _! ?
  }& @! M! q% ^7 C( z
  else if (V_CACHE_FILE) {
8 t$ h1 `4 k' J0 g+ l    v_cache_file_set($key, $value);//1 hour
) b! a; ]: o  o. n* Q8 A    cache_set($key_mem, time(), $table, $expire);
3 l0 A7 G- M$ W! }; b. p  }2 ~  F. C6 i& c4 T, O; w, A% \
  else {% y3 ?3 r3 f8 L6 U6 s
    cache_set($key, $value, $table, $expire);0 G" g/ U& D" v+ Z9 o
  }
+ R$ Y! t/ V$ m% v. E}! X) W8 n9 K: t) r! {
 
7 m# s( }2 ~) @! V2 Wfunction v_cache_get($key, $table = 'cache') {
' A# w( O/ k' h4 z  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {* U# V1 V8 Y& X2 L
    static $static;( y& K$ D* O8 _+ i, d
    $ret = false;
) ]% N4 B. A* {5 Q/ K7 W- ^, ~: D6 {  if (isset($static[$key])) {
% S' r5 n6 }& V* b$ Q8 w) Q    $ret = $static[$key];% \7 u7 S# A- c9 M5 B& r
  }
4 r+ I, x& P% r8 `% P  else {3 R  e/ z: V  _# s8 E) \, C* i) I
   $key_mem   = via_cache_encode_key($key);
' [: j' J& p. \8 B4 [) c   if(cache_get($key_mem, $table)) {: S6 X/ {! m- s7 P' q6 I$ [
     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';. T. Y! e1 N( z7 c4 C$ d
     $value = $cache_callback($key);* }9 c3 Z# [2 [4 X* E, x" ^
     if($value) {
5 k5 @6 i! f8 j7 e       $cache = new stdClass;1 S% {0 ?5 f  [5 z% L- K# x% P
       $cache->data = $value;, e0 B! T: a. X8 u# T
       $static[$key] = $cache;, ]( u% p7 `0 u3 z
       $ret = $cache;
5 R4 h9 s6 y) Q2 |# A7 K     }0 \1 P% _  v; t/ r0 t9 D5 a
   }. {' a$ Y# j- k( @  h9 J" W4 W. n/ b
  }+ _: w( [8 j" x
  return $ret;& q% e3 P( U5 n+ N: r5 j6 v2 z: O
 }
  B- H1 B) Y) t3 }9 e) Z0 c4 o/ D# Q else {
# M5 H# K8 M2 y+ u: E: ]1 l   return cache_get($key, $table);) O! w2 D7 f' K6 T: E
  }
' k7 f/ o! S" F: `7 k}" K( X( @& E* _9 e0 V
 : o" k( N" l% p7 A
function v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
% q7 D% R- j/ L" V  if ($cid) {1 I" \) v! E6 i* B3 y4 U) L" g/ `
    cache_clear_all($cid, 'cache', TRUE);" _  z! e) S( I
    //apc_clear_cache('user');
1 G2 L( v+ b; q( X. i7 D8 Z  }
& R6 `$ H+ z1 U6 A; V; c' I}

添加了上面到代码之后,我们需要修改一些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, 12-19-2025 02:44 , Processed in 0.241688 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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