2012-02-17 88 views
2

我試圖從數據庫中緩存由php腳本生成的JSON內容。但是數據集非常穩定,只有很少的更改或添加。含義數據可能會持續數週。 問題是它包含一個LOB列,只需要很長的時間來加載,比從文本文件提供json的時間要長,這意味着git是使數據庫調用變慢的實際數據庫調用。緩存JSON:Apache,PHP,jQuery

我在分頁(數據表jQuery插件)中顯示數據,並且每次頁面更改數據都會從數據庫中再次獲取,並且還會返回到上一頁。

我嘗試以下操作:

"beforeSend": function (request) 
{ 
    request.setRequestHeader("cache-control", "max-age=86400"); 
}, 

不工作。

我試圖指定mod_expires:

ExpiresActive On 
ExpiresDefault "access plus 4 hours" 
ExpiresByType application/javascript "access plus 1 day" 
ExpiresByType application/json "access plus 1 day" 

不工作。

因此,我假設所有這些設置僅適用於文件系統上的真實文件,而不適用於動態生成的東西?

我更喜歡使用Apache/PHP的可配置方法,因爲我不能完全控制服務器。

編輯之前,首先回答:

注意,JSON包含多個記錄,以便一鍵/值存儲將是一種難以avhieve。密鑰必須包含很多內容:查詢/過濾表達式和所請求的分頁頁面。

編輯2:

Development and prod。都是Windows ...所以memcached是不是一個真正的選擇...

編輯3:

我試過kristovaher解決方案,但不起作用。高速緩存標題是不是在響應所有的時間和一些plaing周圍後,我相信我確定了問題: 我需要使用NTLM身份驗證,並做2請求後不久彼此工作正常,但是,如果你等待位,似乎用戶被重新認證,然後緩存控制頭被「丟失」。

+1

也許有可能,您作爲開發人員禁用了瀏覽器緩存。 – wormhit 2012-02-17 07:44:56

+0

你使用什麼樣的請求 - POST或GET? – core1024 2012-02-17 07:51:47

+0

GET請求。 @ wormhit9:現在你提到它了我記得我曾經這樣做過,但是現在有一個新的FF安裝,並且檢查了network.http.use-cache和browser.cache.offline.enable,它們都是true(默認)。有趣我最近從來沒有任何緩存問題,但按Ctrl + F5通常工作得很好。 – 2012-02-17 08:01:11

回答

1

我玩過一段時間,得出結論,客戶端緩存和使用頭文件似乎不適用於我的情況。也許我做錯了,也許這是我的應用程序或Web服務器配置的方式。

反正我的解決方案是使用APC:

http://www.php.net/manual/en/book.apc.php

我使用Windows,相應的二進制文件可以在這裏找到:

http://downloads.php.net/pierre/

哪一個取決於你的PHP版本及其編譯方式(使用vc6或vc9)。 的php_apc.dll將需要把你的PHP擴展目錄,則需要行

extension=php_apc.dll 

添加到php.ini中

然後你bascially做:

if (apc_exists($key)){ 
    return apc_fetch($key); 
} 
// get data from database because it was not in the cache 
//... 
//add data to cache 
apc_add($key, $result); 

如果我的頁面上的數據未被高速緩存,則需要大約1-2秒才能加載。那不錯,但感覺非常滯後。如果數據在緩存中,則更像20-30ms。當然這種差異非常明顯。

3

緩存控制是一個響應頭。 (編輯:它實際上也是一個請求標題,感謝Gumbo指出它)。你需要在響應中添加這樣的標題(PHP發送的數據)。

<?php 
// How long my cache should last 
$cacheDuration=300; // in seconds 
// Client is told to cache these results for set duration 
header('Cache-Control: public,max-age='.$cacheDuration.',must-revalidate'); 
header('Expires: '.gmdate('D, d M Y H:i:s',($_SERVER['REQUEST_TIME']+$cacheDuration)).' GMT'); 
header('Last-modified: '.gmdate('D, d M Y H:i:s',$_SERVER['REQUEST_TIME']).' GMT'); 

// Pragma header removed should the server happen to set it automatically 
// Pragma headers can make browser misbehave and still ask data from server 
header_remove('Pragma'); 
?> 

但實際上你應該做得比這好。緩存控制標題只告訴單個客戶如何維護這些數據,另一個用戶可能仍然會讓你的服務器重新做這件事。這就是智能緩存系統的樣子:

  • 您生成您的JSON,無論它是什麼。
  • 將該JSON作爲臨時文件存儲在文件系統中。
  • 您使用Cache-control標頭將內容發送給客戶端,使得瀏覽器不再向服務器請求數據並改爲使用緩存。
  • 如果另一個用戶訪問該站點並且他們的瀏覽器沒有該緩存,那麼腳本應該檢查緩存文件(您在第2點創建的緩存文件)是否存在,如果存在,則從該文件讀取數據到客戶端而不是再次生成它。
  • 您還應該檢查緩存文件的年齡,可能每隔幾天再次生成一次該文件。

但是在做這件事情時需要注意很多事情,如果您的緩存包含敏感信息,那麼您必須確保它不會從緩存轉發到錯誤的客戶端。

編輯:

直播例子是在這裏:http://waher.net/cachetest.php(如上所示的相同的碼)。

此文件由瀏覽器從緩存中加載5分鐘。但請注意,如果刷新頁面,它將忽略瀏覽器緩存並仍向服務器發出請求。如果您打開新選項卡而不是刷新頁面並輸入URL,則可以更好地嘗試它,Firebug/Chrome開發工具將顯示文件是從緩存中加載的。

+0

我嘗試過使用標題的簡單方法。我想我可以忍受這一點。我不關心數據庫加載只是響應時間。不過,我厭倦了你的建議,但它不起作用。奇怪的是,緩存控制頭並不總是返回? – 2012-02-17 08:35:20

+0

然後你做錯了什麼,因爲我在一個實時軟件上使用了這個確切的代碼,並且它工作正常(我正在用Firebug和Chrome開發者工具測試它,而瀏覽器確實使用了緩存)。確保你的服務器不會自動設置一些不應該設置的頭來覆蓋這種行爲。給我一分鐘,我會通過一個現場示例在我的原始回覆之下發布測試。 (另外請注意,'刷新'瀏覽器在某些情況下會讓瀏覽器忽略你的緩存,因爲它認爲你不想使用緩存) – kingmaple 2012-02-17 08:44:59

+1

你錯了:[* Cache-Control *](http: //tools.ietf.org/html/rfc2616#section-14.9)可用於請求和響應。它似乎正確地理解了* Cache-Control *語義。 – Gumbo 2012-02-17 08:45:22