免責聲明:作為非英語母語人士,我使用 AI 協助結構化和潤飾本文。
幾天前,我分享了在 Node.js 中實作零配置 S3-FIFO 快取——這是一個探索性的 v0.1 版本,展示了如何使用預先配置的 TypedArray 實作 S3-FIFO(簡單且可擴展的掃描抗性 FIFO) 快取演算法,以消除 Node.js 中的垃圾回收(GC)壓力。
今日,經過廣泛的壓力測試、架構強化以及 100% 單元測試覆蓋率,我很高興地宣布 s3fifo v1.0.0 正式發布!🚀
快速回顧:為什麼選擇 S3-FIFO + 零配置?
傳統的 LRU(最近最少使用) 快取有兩個主要的生產缺點:
- 單次命中快取污染:掃描或順序查詢會用只存取一次的項目淹沒快取,淘汰您的高頻工作集。
-
垃圾回收開銷:基於物件的快取實作會在每次
set()時動態配置節點,在高吞吐量工作負載下觸發頻繁的 GC 暫停。 S3-FIFO 透過將快取條目組織成三個輕量級佇列來解決快取污染問題: - 小型 (S):快速篩選單次命中項目(通常約佔總容量的 10%)。
- 主要 (M):保存多次存取的高頻項目(約佔容量的 90%)。
-
幽靈 (G):記住從小型佇列中淘汰的鍵值,如果重新請求則立即升級至主要佇列。
s3fifo透過使用連續的 TypedArray(Uint32Array、Float64Array)和可重複使用的索引池來支援這些佇列,實現 熱門get/set週期中的零動態物件配置。 --- ## v1.0.0 有什麼新功能?(生產就緒) 雖然 v0.1 專注於核心演算法速度,但 v1.0.0 提供了任務關鍵型 Node.js 微服務所需的所有開發人員人體工學、生命週期工具和安全保證。 ### 1. 💾 冷啟動持久性(dump和load) 防止容器重新啟動或部署期間的資料庫雷擊/快取衝撞。s3fifo1.0 支援將活躍的常駐條目與其原始建立時間戳記和剩餘 TTL 一起序列化:
import fs from "node:fs";
import { S3Fifo } from "s3fifo";
const cache = new S3Fifo<string>({ max: 10000 });
// 1. 匯出活躍快取項目(可選擇性地篩選掉暫時性鍵值)
const dumpData = cache.dump((key, value) => !key.startsWith("temp:"));
fs.writeFileSync("cache-snapshot.json", JSON.stringify(dumpData));
// 2. 伺服器啟動/預熱時:立即恢復快取狀態
const snapshot = JSON.parse(fs.readFileSync("cache-snapshot.json", "utf-8"));
cache.load(snapshot);
Enter fullscreen mode Exit fullscreen mode
2. ♻️ 安全資源生命週期(dispose 回呼)
當快取項目被淘汰、覆寫或清除時,您通常需要釋放外部資源(例如,關閉檔案描述元、銷毀資料庫控制代碼或追蹤淘汰指標)。
const cache = new S3Fifo<Buffer>({
max: 500,
dispose: (key, buffer, reason) => {
console.log(`Key ${key} removed due to: ${reason}`); // 'evict' | 'set' | 'delete' | 'clear'
// 安全釋放原生記憶體或資源
},
});
Enter fullscreen mode Exit fullscreen mode
🛡️ 重入保護:當快取操作完成時,才安全地延遲
dispose回呼,防止回呼遞迴呼叫cache.set()或cache.delete()時損壞內部狀態。3. 🔍 無副作用檢查(
peek)需要檢查快取值以進行日誌記錄、健康檢查或監控,而不影響頻率計數器或變更淘汰狀態?
peek()允許純粹、無副作用的讀取:
// 不會修改 S3-FIFO 頻率位元欄位或 TTL 時間戳記
const val = cache.peek("user:1001");
Enter fullscreen mode Exit fullscreen mode
4. 🔄 標準 ES6 疊代器與 Map API
s3fifo 1.0 與 JavaScript 的原生疊代協定無縫整合:
// 標準 JS Map 風格疊代器
for (const [key, value] of cache) {
console.log(key, value);
}
const keys = Array.from(cache.keys());
const values = Array.from(cache.values());
const entries = Array.from(cache.entries());
cache.forEach((val, key) => {
/* ... */
});
Enter fullscreen mode Exit fullscreen mode
5. 🧹 無洩漏生命週期關閉(close)
在無伺服器、熱重載(HMR)或測試環境中,背景計時器可能會阻止程序終止。close() 方法會清除活躍的背景 TTL 計時器、釋放記憶體緩衝區,並防止記憶體洩漏:
// 在關機時進行乾淨的關閉
cache.close();
console.log(cache.isClosed); // true
Enter fullscreen mode Exit fullscreen mode
📊 基準測試:命中率和吞吐量與 lru-cache 比較
在 Zipfian 分佈(偏度 0.99,工作集 100,000 個鍵值)上測試,比較 s3fifo v1.0 與 Node 流行的 lru-cache:
平均命中率 (%)
| 快取大小(佔集區百分比) | lru-cache | s3fifo |
|---|---|---|
| 1% | 48.90% | 58.30% |
| 5% | 65.00% | 71.10% |
| 10% | 72.30% | 76.40% |
| 25% | 82.10% | 82.70% |
| 50% | 89.00% | 86.30% |
平均吞吐量(ops/sec)
| 快取大小(佔集區百分比) | lru-cache | s3fifo |
|---|---|---|
| 1% | 10.8M | 15.5M |
| 5% | 10.8M | 14.4M |
| 10% | 10.2M | 14.3M |
| 25% | 10.3M | 13.5M |
| 50% | 10.3M | 14.7M |
主要結論:
- 命中率提高多達 +9.4%,當快取容量相對於資料集大小較小時(1%–10% 範圍)——適用於前端資料庫快取或高併發微服務。
- 吞吐量提高約 40%(~14.5M–15.5M ops/sec 對比 ~10.5M ops/sec),因為在 get/set 操作期間零物件配置。
開始使用
透過 npm 安裝:
npm install s3fifo
Enter fullscreen mode Exit fullscreen mode
基本用法:
import { S3Fifo } from "s3fifo";
const cache = new S3Fifo<string>({
max: 1000,
ttl: 60000, // 60s 全域 TTL
});
cache.set("session:abc", "user_data");
console.log(cache.get("session:abc")); // 'user_data'
console.log(cache.size); // 1
Enter fullscreen mode Exit fullscreen mode
連結與回饋
- 📦 NPM:s3fifo
- 🐙 GitHub 儲存庫:BJS-kr/s3fifo
如果您正在尋找 Node.js 中具有掃描抗性和最小 GC 足跡的記憶體內快取替代方案,請試試
s3fifo!非常感謝您的錯誤報告、回饋和 GitHub 星標!🙏
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.