国外设计欣赏网站 - 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(内存共享)、文件。这里我们重点选择文件夹,因为文件夹正常是缓存在磁盘上,但是我们可以把这个文件夹挂载到内存上。如果内存不够可以取消内存挂载,这样操作起来比较灵活,也不需要修改任何代码。

2009 {$ E0 Z7 p. t+ [
201
- J3 B; p7 G1 H( K, v202, `4 B$ h" N3 B, `
203. `- v9 N- l; x* _+ d
204
! o. V4 \8 n9 o# Z8 d8 k205/ x' A& m6 B& j# e4 e" \! p
206
2 {& V0 l1 P- Z3 }9 R, H3 g/ n5 i207: m% R6 W4 @2 M& S3 e2 @  ]
208
1 ~: t) w+ x1 h209; a3 H" F. L: ?9 f/ @5 P
210
0 H: h* ]. G1 X9 o$ u9 ~9 i; `. s2119 x& {+ t. K4 z3 q( x  P
212
' P. |! t3 d. o8 }213
1 g4 |& A; t" f. D214
2 x+ s& m# N" o3 R( g8 u% L215. ^# ~2 s! D% h: H5 a' d! Q7 [
216; f, }/ u8 S+ H) [+ f5 M
217
- D: Z' l# p  a8 [" z# `0 H1 d  O218) ]# D6 w8 X) M$ A
219
" ?- [: T9 F! T0 d( m* i7 \220
* O  i0 H  [5 f. B; _8 A) a221
: ?9 Z2 Y- \5 [, f. t( |1 C222
# T9 E* u  t& d* C3 |223
  X* ]5 ?- S) H( P2 E8 f224. C# I/ b3 S0 z) E+ B  m, Y# z
225! e- G1 {$ a& B/ b: [. `$ m4 _
226
" C# s( @0 N1 h! }, G9 w6 Q! a227
8 P1 G" f- b& Q' \7 f8 ~, F6 X2283 S. y% ~  m* F' `$ I
2290 k: [3 d+ N. T4 f8 F
2300 {; E; A4 K: `' E; u  ?. Q' z
231
8 z% M, {* v) |( b' @232' A( w0 `4 J. v8 x( k
233- t0 P3 i5 r6 }: K, C* n8 H2 [( i3 i
234
  O' I% h4 B- H  g5 i& u235
% j0 T) T' `  D4 C" O' J, {+ R2 N236. ]1 b1 N% Y+ p3 N
237, R' _  K$ y8 G. s
238
1 K' m9 j! _+ F" x$ g( O5 l9 b239! l6 a% h% u8 d- K2 N
240  L/ Q) ~1 E9 Y! m3 f
241' D) ^' t! W/ s' I7 v
242
0 e+ _4 t& g* V3 }) ~2 C0 p* U2436 T( q5 a& w6 j% t& w
244/ d+ o# {7 W3 M, L( Q0 _! a
245
7 ^/ [' `) [0 k' n2460 i% r+ v) J) T' T% h
247
& X0 W: x% e5 p% J) {248
4 g% q2 N, A- f3 b249/ y3 n- a  P! k5 g( X6 A
250
: A+ w, `# g0 g& W" g251
) l1 t, T5 k9 }252
/ o0 K# o3 y: T$ p: n/ o5 f* v253
0 ?6 {) c8 r8 i8 ^0 H+ o254
6 e: F) _& g% D8 {255# q' k" _1 r: H8 N$ L
256
" I$ o/ C3 R( T+ `& B/ I257: w; X+ x/ Z9 ?" ]
258* Q/ W( d9 Y) g2 p% E
259
5 e: R- i0 l' t4 n" Z260
& j- r( h& M2 v' P9 g9 [3 t4 h261
& Q7 w$ t0 p/ q7 m! w; ?9 m1 N262. D7 I; g2 J- c0 j& L
263$ I% Q$ R8 v# H' S- U, A' i/ T, R
264! F7 N9 g/ z# k
265
5 g0 S" T0 o0 W$ s9 U3 }7 ^. r3 X! S2660 y! {8 O7 {, h% q& @: i) w
267& Z+ s% f* s! z& }; B
2683 _# D/ `6 ^7 W' S. n/ S
269
2 L+ z# r4 b3 O; E  b9 x" O, d6 f270/ ~# w" D; n! r, y1 I: d* X1 P5 p' Q+ t
271* L3 b& y3 U3 J
272) S1 _: X) N" x: F+ Q
273
# g, G" p* U3 {274: R$ w* P! [, B3 }! ^5 ]- l; V
275
! t9 |& V0 Z* V) K# ~' o) ~2760 k- A1 ~" u! \; L  n1 W/ `; i
277
* K# ?) r8 }, ]! }. _* T4 Y) l% X278
7 C* n3 H2 ^6 e5 d( b279- s& A2 P5 L) X
280
3 @% p: N, C6 j0 ?281
3 k& |* f+ r  }6 F: x6 Y+ `282
6 W5 A, l: _: z& E283
8 N* C0 u3 E2 I) ~284$ x" j9 {; y3 U7 d9 N
285& V' k$ U% i* y% b* K
286
- x" S+ f9 C1 ^* q8 o# ]7 o2871 s' I9 T$ o& L% p
288: ^. @+ W$ I; q/ v! l" |. B
289
! I" F7 t  r9 t290/ D6 u* |, j3 j' d5 A( Z$ V6 t- H( P
291  n5 V2 e4 o) l
292
4 G5 C/ t9 [4 K' q293
* u# {. s( b" m- C! P( [9 q1 G294
  g) c. F- f* x' r: ?4 f2956 @' s, {7 o2 G% N& O- U
296
  l. t3 e7 M5 H6 s, S6 N2971 u+ n+ ^. `& t# V
298
3 ?1 O( `! b# [( N, E299+ O. p5 |3 M1 l
3006 C2 {0 H: J; `) U' M. b3 z
301& Z% ]$ i/ _3 T1 T0 A
302& f& i7 r, `: e9 r. u
3033 z, u8 y5 R2 R& z6 G, f1 T
define('V_CACHE_FILE', 1);
0 V0 \* @3 D/ d, s! m 
% F7 j2 |) @( {/**
8 {8 t3 D) t2 G  h$ P3 B" z  s# x( \/ R *@important Create the cache folder to store the cache data firstly; S; u+ m  h) d) `. G' V: V
 
; u$ X, j6 v& J8 D   #create memcache local cache folder
; d( {( B/ m9 k4 i3 V7 F0 u   mkdir memcache ; sudo chown nginx:nginx memcache
6 l1 z  n  F. {0 N6 R8 I% ~ 
) Z0 F! `% w& \1 C7 l8 l& _ */
4 v* t# J# d, R) V( X9 b2 X* f8 gfunction v_cache_file_dir() {% m7 Z( j( V5 C1 z, r: w: ^3 C9 p
  $path = dirname($_SERVER['SCRIPT_FILENAME']);5 i# l. }. y4 _7 ?$ }2 @8 q8 Z5 @
  #$dir  = rtrim($path, '/') .'/'. trim(file_directory_temp(), '/') .'/memcache';% R# r- E8 L9 r5 E6 c# I
  $dir  = rtrim($path, '/') .'/memcache';4 e$ Q# H/ A- n  w3 h
 6 Y6 A' `; O& I1 X3 y' d- b
  if($_GET['debug'] == 'test-cache') {1 S# ]% m: w) }/ X
    drupal_set_message($dir. '@DIR');
" `( ~3 P- y( Y% m- ~6 v4 @  }, S( f3 |  }/ q) s8 v+ h* B, U- L& e1 Z
  if(!is_dir($dir)) {
9 ^5 C) @! w! q1 f& W    #mkdir($dir);
6 v4 c: r4 H4 x, f  _- d    throw new Exception('Create local directory for cache, ' .$dir);
3 t4 U3 V0 P" b* ~. Q8 c$ L  }# O9 ]! w8 h+ c. c
  return $dir;  n2 v0 ]# u$ M, W! z) v: S9 a3 S
}# h2 W( o$ m, k$ R3 r6 r6 M* v
 , Q5 ~7 A# {7 C
function v_cache_file_set($key, $value) {
6 X' }5 N! f* e. |  $dir = v_cache_file_dir();
" s# H& ]: Q/ a6 a& @% }; @6 q  $file = "$key.ser";+ x% L, D2 R0 G0 F* G& G
  if($_GET['debug'] == 'test-cache') {; ]0 U/ }0 x9 \; C' o6 K+ z
    drupal_set_message($key. '@FILE_CACHE_SET');
3 c9 h* [- K: X) i  }: z1 b5 G) H1 X# ?+ e6 v& s
  file_put_contents($dir .'/'. $file, serialize($value));
, ~5 J( g/ d4 p  q. K5 m% A. }}
% v  W4 ]& F2 K/ z 
% n1 c) N* o7 M) Z4 qfunction v_cache_file_get($key) {; j0 F) {+ A" ], O+ s: t' E0 y: |
  $dir = v_cache_file_dir();' ^9 a" g# ^2 t0 k, |
 
( w& z3 `) c3 j0 {, w$ ^( `" [# O  $file = "$key.ser";6 \- ~0 o' Q  M
  $file = $dir .'/'. $file;
7 d; b' g6 |& l  if(file_exists($file)) {
) W) v* a* o  p9 h  x# Y* G     if($_GET['debug'] == 'test-cache') {
  R/ I' i& ]  ]' U0 t6 q      drupal_set_message($key.'@FILE_CACHE_GET');( Q  c: Q5 r: J+ v9 G
     }
! M  j, Y' C! `5 e7 ], l1 b- Q( U5 N    return unserialize(file_get_contents($file));8 P; x4 f+ t% c% P2 T% s/ R
  }) q! P7 e$ @- a8 g- Y
  else {
% p& A  [* o4 V: v- z7 H; N    return false;
# M) S# P; p- W$ `2 K* [. {  }
  X1 i5 A) g7 N; y) x; Y}
) o0 W4 W- x/ E5 k. Y / e4 ^. X1 A1 a% x
function v_cache_encode_key($key) {
1 H2 ~  k$ ~6 k1 E# v; w# M  $address = $_SERVER['SERVER_ADDR'];/ W* x$ C0 q: z3 ~- t
  //$key     = str_ireplace(':', '-', $key);
+ E6 `* ]% d4 h+ s# S  $key = "$key:$address";8 ~4 R6 U$ _# x' Y, Y4 P
  return $key;
, r7 h$ U2 C# {( O}
; {2 d8 j1 {  e" S7 H   h+ [+ F6 ~5 p: R0 T# a
function v_cache_set($key, $value, $table = 'cache', $expire = CACHE_PERMANENT) {' ?, Q1 a  `: q3 S7 T: m
  $key_mem = v_cache_encode_key($key);
& K5 N' n3 `& [! M9 N8 h& }  if (function_exists('apc_cache_info')) {0 o) q/ i* Y; l
    apc_store($key, $value, 60*60);//1 hour
' C# p0 |7 E6 b; k7 O; o    cache_set($key_mem, time(), $table, $expire);
% j( ?/ @% _5 n6 o- x* P; Q' a' O  }
7 ?- P# _7 h# G" V$ y  else if (V_CACHE_FILE) {
) X0 L2 {7 O" d% \3 H; _    v_cache_file_set($key, $value);//1 hour/ F9 p1 q, W; e: e: I: B
    cache_set($key_mem, time(), $table, $expire);
+ z( e, `$ D3 ]  e5 u* v4 A  }1 P! a. I& `' Q' [8 F, [, F# n
  else {
/ B9 E0 g3 n4 [0 I0 b, D: K    cache_set($key, $value, $table, $expire);& k0 E, D8 J% X% O* v
  }
+ e  o! L" t  Q% Z- V}
, W9 q; `6 {! Q5 b 2 O7 x7 n. k6 B+ F: v6 {
function v_cache_get($key, $table = 'cache') {/ g' I4 e' L5 c9 h) B5 `. g
  if (function_exists('apc_cache_info') || VIA_CACHE_FILE) {
; |5 ]7 A/ j! c0 y1 o, m    static $static;, o4 ]* I* A* B% O' ?% D
    $ret = false;! |# ^4 O9 V* E! h5 R' Y; I
  if (isset($static[$key])) {
2 }9 z4 x5 z( J% t8 O" `* Q    $ret = $static[$key];
$ z  E+ ]9 i) f" y0 f  ~  }9 I5 ]% h5 v5 f7 `! t
  else {
; x. {6 e8 a2 n; L   $key_mem   = via_cache_encode_key($key);1 g  r& |2 N. t  m/ ^) h1 z2 d8 I! G
   if(cache_get($key_mem, $table)) {
8 J  u1 F6 o0 S2 T2 Q     $cache_callback = function_exists('apc_cache_info') ? 'apc_fetch' : 'v_cache_file_get';
( q) e7 O) y. T: _     $value = $cache_callback($key);% N1 g% H2 ^7 d3 G, |
     if($value) {2 @; \0 l4 L1 h9 C3 w
       $cache = new stdClass;
2 R2 f3 S5 |, j8 P$ p       $cache->data = $value;. K4 o4 K# p1 g5 C0 z! R
       $static[$key] = $cache;* H4 O; f: t; w# U
       $ret = $cache;
. O) t& e+ @  f& y* n! ^     }1 E  u8 X! j/ u. G' m& Q' x7 j
   }, d7 A' W4 Q" Y# o$ c) u
  }# _8 t) H# y# r3 y
  return $ret;
( J" R: Z/ n2 f4 d" U, p }# ]( {# S" s0 F
 else {
% _! V0 H) b7 w4 K6 c! ]5 O3 _   return cache_get($key, $table);- ~& g: Y7 i9 C+ c, @
  }8 U1 ^3 b( V0 [- C8 x$ z
}
" D; O) @# t& Q" ? 
: Y% ~/ r. `6 a% Y( ~3 q6 S) Xfunction v_cache_clear_all($cid = NULL, $table = NULL, $wildcard = FALSE) {
6 H8 w/ a/ p5 d" z$ H- E: k  if ($cid) {+ R" Z( [/ @# a  t
    cache_clear_all($cid, 'cache', TRUE);
6 w3 R9 v$ J3 a+ J    //apc_clear_cache('user');3 V1 }8 X. {4 \" `/ o/ |  f3 C) P
  }
6 W5 Q9 }6 f+ z4 W}

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

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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