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 | var Cache = require("ds-cache"); |
結語
起初為什麼會想要開發這個 Cache 機制呢? 首先,我去找幾個以儲存為 JSON 檔案的 Cache 套件,但沒有一個是以 JSON 檔案大小為 Cache 緩衝區長度限制,所以~才會自己去勾出一個這樣東西。其次,是想在查詢後,將每一筆結果保存下來,但不是永久性保留下來,而是給它一個保存期限,故選擇使用 LRU 演算法來完成是在好不過。
為何不使用 memcached、Redis 等成熟技術? 理由是如果專案規模不大,並不需要使用到這種等級,ds-cache 會很適用,單純的檔案讀寫及 JSON 處理,沒有額外負擔處理,這是 ds-cache 好處。
最後,希望這個小東西能對你有幫助。 XD
參考資料
文件
- Wiki - Cache Algorithm
- InfoQ - 在Node.js中搭建缓存管理模块
- LRU缓存置换算法 | Jim Liu’s Blog
- 如何设计一个LRU Cache? - hexinuaa的专栏 - 博客频道 - CSDN.NET