国外设计欣赏网站 - 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  ?3 ?. b% V  ^7 e2 x
201
2 G  {, x0 p+ }5 t9 v+ d* A202
3 G& e" F' t3 g9 g3 F4 G203
7 ?: @1 P1 I9 _4 o  H7 E204
8 ~  l( p) A! `' P1 B205( q  @/ I4 ~+ `( B
206
3 z0 }8 u- e, H% w207& l4 j* n$ g2 f1 O) R  g( v
208
/ k- B: r7 |2 o/ e, V209
! M3 X) n, A5 q3 R( i. D% Y5 s2 k210$ E9 K# J, h' \. s! h5 ~
211
$ G: H6 V4 @" p8 D; v2127 P0 g* w! W: u$ \$ H& ?
213* G9 L7 [/ k4 f! Y
2147 L% g$ X4 X; Q8 z
215
0 |7 X( H1 A* |216
; y- A: K. B9 J# n- r/ g/ [217( U, c! H0 Y/ R2 L, ~
2181 U4 x( I' E; D2 [& r; t/ V
219
6 p6 w7 |5 W2 A220' ?5 o; w3 w' N
221
+ }* T9 k" D" @( e222
1 U3 [- {9 v. \223" f4 n4 e* Q2 r- o: w6 c' @
224
$ U* N1 L! P0 {( T0 A225
4 u; {# W; o/ K8 X" S: v2268 [* i  Z; {' c* V: x& a* W5 g
2276 F# j: ~$ R: P5 S
228
5 E. J, d# @: G0 |+ @229
. k( r, r" \) T0 ]% z. O230
$ q8 [  _7 U* _) V0 a3 f. k& F9 A231
  P# X  p3 X8 B8 x232% Q2 Z' p$ X! V# ~7 a
233/ B% m7 C: K8 ^% M! p- R
234
/ f$ f, `; x( R  u, }235
/ |, O4 m8 G9 [3 u  V236
" q  k$ Z3 w/ x1 t- I% b. V, N+ S. `237( R3 Z9 X) r) F3 A9 ~
238
5 k) {  N( Z1 C3 k239" P% V8 H" T9 m  F, P& w; J
240
2 w' L, a; O, x241+ n9 G& P; q$ `% G) j0 k/ i2 ?
242
# u5 l: Q5 x( W243
$ w! i) Q$ |* S8 a6 N2441 J# v. L  y( A+ o3 B4 E
245
+ h) |, g- P+ A( e7 n$ [246
  Q6 V, }- Y, Y4 x. \' m. J3 M247
& v9 s# a5 P" [$ S248% C* M- H; n. v8 Q0 B
249
+ [4 T  k: o3 ^+ i+ X2 ^250
0 Y7 w7 T+ ^& Y# O251( ]0 s0 I5 |. y* w9 Z% l8 r
252
6 d) C2 Q3 r% G* y) e: h253: p3 P$ Q8 m+ o. t0 V
254
, `9 p5 m( ^7 {' n" }255& A4 [$ R* t8 W3 f7 X5 U
256
9 X& }7 C8 v; J4 _257) n0 D+ v0 E& y2 i- ~
258
, t8 m, c3 N" [1 f& }2 Y! K) C) x  Z2 @259
9 [# l! F+ S/ w4 s$ k260
) |: k; `- E, a! u, A5 f261) ]2 J+ L+ L: g6 D+ K* j1 m. C9 q
262: _$ U3 S8 G9 @9 d
263
, Z( j* a2 e- N: A264, W: @0 ?% n6 {" [0 \
265
, C- {9 [) U, F# _9 C266
3 g8 Q* o7 ]9 s: ~267
! B6 Z, ]) C/ |% w. w& R. I$ P' p% D268
$ h6 L( H2 ~& x8 n! ~4 V; A269
# w( M4 c. x* U$ a$ q270
1 w9 R: `& L5 n1 a271% l4 m3 x& L4 K. {5 Z' N" d
272
! I6 O( ~9 p' ~8 ~273
/ g2 b. M! e3 S# B* J% F274' O' i5 y" o3 R: G
275  s! B0 B( a1 Y: t$ L
2762 @1 h5 p2 p6 @# O
277$ M/ q# B2 }; q5 |" O$ _
278
- T% Q8 d4 j' S, E2797 L+ g+ s! r9 e$ ^+ C& l8 g" C
280' a6 H4 n" [. \
2812 H) r' _8 n, z
282
7 N) d1 E! x5 w. u2838 o. u, t' ^0 G
2841 v1 K7 D9 P' ~, Z5 z" D
2850 X, _# B5 T( {" V1 |
286! @- e( Y4 |; q9 V8 N
287# ?! @  ?' Z5 z. [4 K# h$ O2 X
288
' \* i$ a& Y! a- Q, Y289
3 q5 U* h5 p# O9 f* l" m5 o290
, H+ W# Q/ M8 e# ?4 _& Q7 H2914 L# q% e2 s. Z' |2 \0 |) E
292
1 e; e+ M1 X8 z7 t293* ]# f1 I* m% ]
294
2 z$ }9 T, _3 G9 C3 n; F. l295
; G# O1 m* t8 F; F9 ^296& K: a9 D9 i+ N# y- T5 ~
297! L6 _$ J2 B# J1 U
298
7 O  e/ z5 o% X+ K+ F/ f299
0 t# h1 h5 e1 P& V% K9 F( R) |* O# p300
( J- S5 P$ E! d" [1 P, s+ q. Z301
& U' B/ g' @3 W6 a) m4 ^302
3 R; i4 I7 y7 }! {! @5 a! {303
3 R; n5 U+ T' [2 ^1 ^( ^
define('V_CACHE_FILE', 1);& i) c( F1 t1 C5 S
 . G$ T$ r; F8 H9 Z0 ^( t
/**
) M8 K0 t8 U9 U. x *@important Create the cache folder to store the cache data firstly
" m" n. a" @7 Y$ P* { 
4 a; v1 `+ r! T# r" l" V   #create memcache local cache folder
9 V* w& ]: g4 E" Q5 `: G' X: R; t   mkdir memcache ; sudo chown nginx:nginx memcache
( I( D/ F+ B+ W5 H! r; ? ) y  h# z& R9 |2 P, S: A
 */
& \* B' S4 t: W8 Jfunction v_cache_file_dir() {
6 N; t; A( f) I8 r* c, N. d. e% f  q  $path = dirname($_SERVER['SCRIPT_FILENAME']);7 q: a( s& S# R& W8 a6 n  Y
  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';
: i1 J# q( g' Z  $dir  = rtrim($path, '/') .'/memcache';  ]0 l8 Q  e8 a$ f( {8 u% L
 & p% N6 P* U4 |% }
  if($_GET['debug'] == 'test-cache') {; W& A5 _! T: V3 N- {9 L% A! B
    drupal_set_message($dir. '@DIR');8 @8 J- L8 f& Q. p% A
  }
0 E" X% M, t# X' C- m* H1 p( d  if(!is_dir($dir)) {  f4 N0 @* B, g4 a
    #mkdir($dir);
- T  M; }# c1 S    throw new Exception('Create local directory for cache, ' .$dir);
( P: U' z. `$ x( Y" f  }6 _& q, N: y  S, D! {
  return $dir;
( V" e/ J( A, c2 u1 h1 a}2 \* J5 O" d- h
 
' ~8 B6 C* q0 z& Q* k+ n* Q  zfunction v_cache_file_set($key, $value) {
+ ]6 |3 D' d# o" F; z% W  $dir = v_cache_file_dir();
: w) `$ [( O( B, M; |  $file = "$key.ser";+ W9 E  ~: T, P5 g6 U1 g0 s* q
  if($_GET['debug'] == 'test-cache') {
" r9 M  [6 f# U0 Y/ R, ~    drupal_set_message($key. '@FILE_CACHE_SET');6 E" a% l8 x) B5 C- ^9 {  B) F
  }
% M7 x( ^: P, _6 N4 H2 G  file_put_contents($dir .'/'. $file, serialize($value));2 d" {5 @* u5 a4 d+ w% A
}
* G. n. r' w7 J' U 
0 J& P* w* o% P. O+ n: ^7 H% Gfunction v_cache_file_get($key) {  {  ^" H* Q; f
  $dir = v_cache_file_dir();
; d/ ~, L! ^; S+ d# M! t; r 0 C* l0 |" ?) ]7 `' v3 U/ I& D0 o1 Q
  $file = "$key.ser";7 b2 k1 X; s$ h& a9 H; D( w
  $file = $dir .'/'. $file;2 Q+ |1 u( L' N
  if(file_exists($file)) {  s: K; i. ]- U; f
     if($_GET['debug'] == 'test-cache') {$ L+ m) j$ [  i% [# J
      drupal_set_message($key.'@FILE_CACHE_GET');7 r$ q. f: C2 X8 A
     }: ]+ M. |9 ^3 f( t* A  A" Q& R
    return unserialize(file_get_contents($file));6 F0 j7 I% v0 Y* k5 {* v
  }6 Q# ~" `) h2 s" V1 Z) P$ I
  else {9 q/ n7 O" \7 x6 U4 F4 j: W
    return false;
" ]- Y2 n& h2 j) P9 o) F# h  }) p% Z7 t7 e7 N) M5 G" G
}) T$ A6 }0 F# r( D" ?. z
 
) l  O8 V) w# @% v5 c5 b+ A6 pfunction v_cache_encode_key($key) {3 g9 p7 O1 \, o6 E# J
  $address = $_SERVER['SERVER_ADDR'];0 k/ X4 J9 a1 H" f; Y
  //$key     = str_ireplace(':', '-', $key);
" E/ p# m; s" y+ Q( q* s8 Q4 q  $key = "$key:$address";
2 z0 n. l2 [2 l9 Y$ t  return $key;
0 m" x8 g5 Y( ~}+ {% ^* a7 l: T! g
 
' G; n/ O' \+ Y; T+ i$ G0 h, M8 wfunction v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {
  Q/ v6 t* {& s7 f8 i1 g  $key_mem = v_cache_encode_key($key);
# s5 L* y" r: F. ^7 J! B& b+ J  if (function_exists('apc_cache_info')) {% K- N. J7 r/ x! R8 @5 B
    apc_store($key, $value, 60*60);//1 hour
8 z, T4 _0 b, j4 U    cache_set($key_mem, time(), $table, $expire);
& r) R. a% o5 @  u5 J7 f9 J0 |  M  }6 K6 F  e) _, I& c+ D0 \1 O
  else if (V_CACHE_FILE) {; O% p1 z" }. d3 B+ @
    v_cache_file_set($key, $value);//1 hour
8 R5 w8 [& d3 A- e    cache_set($key_mem, time(), $table, $expire);
9 `, }1 `4 h( W$ l! T8 Z0 `  }
( L1 N/ V' W' h1 S) Z  else {
" Z. ~, j) {+ h7 y0 R    cache_set($key, $value, $table, $expire);
+ r( R4 s% V6 M, ~3 D5 f& {  }  m4 M/ h% {: J# E2 `! N8 @
}$ G! N! [3 a2 ]
 6 }2 M" W! D( e1 |6 P
function v_cache_get($key, $table = 'cache') {, I' l3 ?" h( T, K
  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {6 S% _2 R, L" ?: Q# y3 @" r
    static $static;
  q3 @! g( s- C! W$ Y* k+ L1 x- F6 S    $ret = false;; g  }3 Y# U* I2 P9 D+ S
  if (isset($static[$key])) {/ t4 s) y' K6 z' c* F# u- F
    $ret = $static[$key];
* R& b9 k# f7 E. V4 U- d5 M  }
! q& @4 _5 ^" {8 y6 R" l9 t  else {6 h+ P% s. Z% j* I6 v
   $key_mem   = via_cache_encode_key($key);- k2 H; Z2 V( A# v
   if(cache_get($key_mem, $table)) {
7 B# G  ]7 D9 l+ G% d$ \     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';
2 u7 N: W7 Z3 U     $value = $cache_callback($key);# P8 N% \4 K: T' E8 a
     if($value) {9 T+ n4 @2 s' k( U
       $cache = new stdClass;
- H; Z; f! Z4 U       $cache->data = $value;2 ?# d& b  r8 ]6 m# E6 c5 R
       $static[$key] = $cache;
7 k; Z  y- B7 O0 a* l; I$ Q: {4 V       $ret = $cache;7 T* B; q, `# m% }3 f0 Y) `
     }) S1 W4 e6 c0 x# X' h
   }
& A$ [' ?9 J4 m. ?3 |$ P  }
6 r2 |" d/ g* f  j  return $ret;
2 T  C7 Z- t; I! ?, m6 T6 m) j }5 z) E" [! F0 r4 ~
 else {
$ {* @1 D! w( G% |   return cache_get($key, $table);
/ T2 W% Y% D# ?) E$ W2 h& x- v* g  }
7 b) B/ @+ N/ d! x/ z}" _% R# P' H/ i& I& g8 {2 S& m
 
7 M$ S( E, u' }! g( u0 x" Lfunction v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {4 V/ w" q+ [/ T# b6 |
  if ($cid) {
- k4 D3 t. e( L; K2 F7 q6 D) q    cache_clear_all($cid, 'cache', TRUE);
. K9 b3 s0 e5 d7 H" A    //apc_clear_cache('user');* g5 w+ F" F0 }, m2 `9 E- T0 A8 U4 G0 f: n
  }4 E: I7 Q7 ?/ S* H: S$ S, d3 c% A
}

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

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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