ds-cache

目的

ds-cache 提供簡單的 LRU (Least Recently Used) Cache 機制,並以 JSON 字串讀寫檔案,Cache 緩衝區大小即是設定檔案限制容量,當加入資料發現已超過設定檔案限制容量時,則會開始使用 LRU 演算法釋放所需空間。

LRU Cache Algorithm

Cache 設計用意,是用來緩衝兩種不同讀寫速率之暫存空間,因 Cache 空間有限,故需要一套存放資料的管理機制,來解決 Cache 塞不下的冏境! 在 Wiki - Cache Algorithm 有詳細介紹幾種 Cache 讀寫管理演算法,其中 LRU 演算法最常被使用,核心原理如同字面意思一樣容易瞭解,即是替換最久沒被使用的 Cache 內容,因最近被使用到資料,比起已經閒置一段時間資料,能被重新使用機率較大,故很適合套用於暫存熱門查詢結果情境。

介紹

ds-cache 程式碼簡短容易瞭解,原因除了是由 coffeescript 撰寫外,最主要是因為 功能並沒有很多。 :D

雖然~ ds-cache 很陽春,但還是可以講一下實作 LRU 概念, 典型 LRU 是用 hash map + doubly linked list 來完成,因 NodeJS 語言特性,可以不需要使用 doubly linked list 來增加複雜度,改採用 Array 物件取代,ds-cache 會用到一個陣列和一個 Object 來當 hashmap ,在程式碼可以看到這兩個變數,分別是 _queue 和 _cache 。 _queue 作用是記錄現在所有儲放在 Cache 資料的 Key 值,存放順序代表資料使用頻率,越是後面資料越是不常使用,若 Cache 資料有異動時,同時會更新 _queue 陣列順序,另外, _cache 作用是依照 Key 值,快速取得內容,這便是 hashmap 好處,下面會解釋 Cache 異動時, _queue 和 _cache 兩者變化關係。

  • 新增資料

先判斷 Cache 是否已經全滿,若全滿就要清除一塊可儲放空間出來,作法是從 _queue 陣列由後往前抓 Key 值,在一一刪除在 _cache 對應資料,就是從最久沒使用的空間開始清理,清到足夠能放進這筆資料。空間釋放完畢後,接著 將這筆 Key 值放置 _queue 最前面,而 _cache 則加入這筆資料;若是空間足夠就不用清理,直接放入資料,同時異動 _queue 和 _cache。

  • 取出資料

依 Key 值尋找資料,如果沒有這筆就傳回 null 值; 若有找到就傳回資料,同時在 _queue 陣列,將這筆 Key 值移動到最前面,表示它是最近才被使用。

API

  • clear(key) - 依 Key 值清除 Cache ,若 Key 為空值,就全部清除 Cache。

  • save() - 將 Cache 轉成 JSON 字串後,寫入檔案,若啟用auto_save ,則可以不用在手動 save。

  • load() - 從檔案讀取 JSON 字串後,轉成 Cache。

  • size() - 傳回存放在 Cache 資料數量。

  • content() - 傳回 Cache JSON 字串。

安裝

1
$ npm i ds-cache

範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var Cache = require("ds-cache");

// initial cache instance
var cache = new Cache(
{
limitbytes: '2M', // limit file size
autosave: true,
filename: 'dscache.json'
}
);

// add a data
cache.set('name', 'Donald');

// get value via key
cache.get('name');

// clear data via key
cache.clear('name');

// clear all data
cache.clear()

結語

起初為什麼會想要開發這個 Cache 機制呢? 首先,我去找幾個以儲存為 JSON 檔案的 Cache 套件,但沒有一個是以 JSON 檔案大小為 Cache 緩衝區長度限制,所以~才會自己去勾出一個這樣東西。其次,是想在查詢後,將每一筆結果保存下來,但不是永久性保留下來,而是給它一個保存期限,故選擇使用 LRU 演算法來完成是在好不過。

為何不使用 memcachedRedis 等成熟技術? 理由是如果專案規模不大,並不需要使用到這種等級,ds-cache 會很適用,單純的檔案讀寫及 JSON 處理,沒有額外負擔處理,這是 ds-cache 好處。

最後,希望這個小東西能對你有幫助。 XD

參考資料

文件

Github

Gist