2016-08-08 20 views
0

我有一個簡單的PHP腳本,用於計算給定字符串輸入的一些內容。它將結果緩存到數據庫,我們偶爾會刪除超過特定天數的條目。這種基於文件的數據庫方法的可擴展性如何?

我們的程序員來實現這個數據庫爲:

function cachedCalculateThing($input) { 
    $cacheFile = 'cache/' . sha1($input) . '.dat'; 
    if (file_exists($cacheFile) { 
    return json_decode(file_get_contents($cacheFile)); 
    } 
    $retval = ... 
    file_put_contents(json_encode($retval)); 
} 
function cleanCache() { 
    $stale = time() - 7*24*3600; 
    foreach (new DirectoryIterator('cache/') as $fileInfo) { 
    if ($fileInfo->isFile() && $fileInfo->getCTime() < $stale) { 
     unlink($fileInfo->getRealPath()); 
    } 
} 

我們使用Ubuntu LAMP和ext3。高速緩存查找的條目數量是多少?是否爲非常量或違反硬限制?

+0

我可以建議http://serverfault.com/questions/43133/filesystem-large-number-of-files-in-a-single-directory作爲一個很好的起點嗎?海事組織更像是一個「明顯較慢」的問題(也就是說,減速是否會影響工作流程)而不是「非常量」(我認爲這種系統本質上)。 – fvu

回答

1

雖然這特定的代碼是不是很「可擴展性」 *可言,有一些東西可以改進:

  1. SHA1需要一個字符串。因此,在計算哈希值之前,非字符串$輸入變量必須先序列化或json_encoded。只需更改命令以防止意外輸入。
  2. 使用CRC32,而不是SHA1,它的速度更快(Fastest hash for non-cryptographic uses?
  3. 目錄「緩存/」是相對於當前目錄中,以便在頁面工作目錄的變化,因此將緩存目錄。將會有人爲高數量的緩存未命中。
  4. 每次將文件存儲在cachedCalculateThing()中時,都會將該文件的名稱存儲在/ dev/shm/indexedofcaches(或類似內容)的索引中。在調用file_exists之前檢查索引。 ext3速度很慢,緩存以及內核ext3索引將被分頁。所以這意味着每次詢問file_exists時都會打擊目錄掃描。對於小型緩存來說,速度足夠快,但是大型緩存會出現放緩。
  5. 寫入將會阻塞,因此當緩存爲空時將會觸發服務器負載限制,並且當兩個或更多php編寫器同時嘗試寫入先前不存在的緩存文件時,緩存文件名上會發生衝突。所以你可能想嘗試捕捉這些錯誤和/或鎖定文件測試。
  6. 我們正在考慮這個代碼在一個有點處女的環境。事實是,寫入操作也會根據當前的磁盤利用率阻塞不確定的時間量。如果你的磁盤是空轉的,或者更老的SSD,你可能會看到非常慢的寫入。請檢查iostat -x 4並查找當前的磁盤利用率。如果它高於25%,那麼放置磁盤緩存將隨機增加到100%,並減慢所有Web服務的速度。 (因爲對磁盤的請求必須按順序排隊和服務(一般情況下)(不總是,但不要在其上存儲))。
  7. 根據cachefiles的大小,也許直接將它們存儲在/ dev/shm/my_cache_files /中。如果它們都能很好地適應內存,那麼你就可以使磁盤完全脫離服務鏈。然後,您必須執行cron作業來檢查整個緩存大小,並確保它不會佔用您的所有內存。缺點=不持久。儘管如此,你也可以對它進行備份調度。
  8. 不要在運行時/服務代碼中調用cleanCache()。該目錄迭代掃描將會超級慢並且阻塞。

'*對於可伸縮性,通常根據線性請求速度或並行服務器資源來定義。該代碼:

  1. ( - )根據cleanCache()函數的運行時間/位置 - 它有效地阻止了目錄索引,直到掃描了高速緩存目錄中的所有項目。所以它應該進入一個cron工作。如果在cron/shell作業中,刪除過期緩存的方法要快得多。例如:find ./cache -type f -mtime +7 -exec rm -f "{}" \;
  2. ( - )對於小文件和非常大的目錄內容來說,提到ext3-ext3的索引和結果速度是相對較差的。谷歌noatime的索引,如果你可以將緩存目錄移動到一個單獨的卷,您可以關閉日記,避免雙重寫入,或使用單獨的文件系統類型。或者看看你是否有可用的dir_index作爲掛載選項。這是一個基準測試鏈接:http://fsi-viewer.blogspot.com/2011/10/filesystem-benchmarks-part-i.html
  3. (+)目錄高速緩存條目比使用數據庫複製更容易分發到其他帶有rsync的服務器。
  4. (+/-)真的取決於您將要存儲多少個不同的緩存項目以及訪問頻率。對於少量的文件,比如說10-100,小於100K,頻繁點擊,那麼內核會將緩存文件分頁保存在內存中,並且根本沒有看到嚴重的放緩(如果正確實施)。

主要問題是,爲了實現真正的可擴展性和超出緩存系統的良好性能,需要比短代碼塊顯示更多的考慮。可能會有比我列舉的更多的限制,但即使是那些受限於變量,如大小,條目數量,請求數/秒,當前磁盤負載,文件系統類型等 - 外部的東西到代碼。這是可以預料的,因爲緩存在代碼之外仍然存在。列出的代碼可以用少量請求執行緩存的小精品集,但可能不適用於需要緩存的較大大小。

另外,你是在線程還是prefork模式下運行Apache?它會影響php如何阻止其讀寫操作。如果$ input已經是一個字符串,它就是它的基本形式/已經被計算,檢索,序列化了等等。如果$ input是關鍵字,則file_put_contents()需要放入其他內容(實際變量/內容)。如果$ input是要查找的對象(可能是一個很長的字符串,或者是一個很短的字符串),那麼它需要一個查找鍵,否則沒有計算被繞過/保存。

+0

看起來不錯,謝謝你所有這些實際考慮。 –