JeongSeop Byeon

免責聲明:作為非英語母語人士,我使用 AI 協助結構化和潤飾本文。

幾天前,我分享了在 Node.js 中實作零配置 S3-FIFO 快取——這是一個探索性的 v0.1 版本,展示了如何使用預先配置的 TypedArray 實作 S3-FIFO(簡單且可擴展的掃描抗性 FIFO) 快取演算法,以消除 Node.js 中的垃圾回收(GC)壓力。

今日,經過廣泛的壓力測試、架構強化以及 100% 單元測試覆蓋率,我很高興地宣布 s3fifo v1.0.0 正式發布!🚀

快速回顧:為什麼選擇 S3-FIFO + 零配置?

傳統的 LRU(最近最少使用) 快取有兩個主要的生產缺點:

  1. 單次命中快取污染:掃描或順序查詢會用只存取一次的項目淹沒快取,淘汰您的高頻工作集。
  2. 垃圾回收開銷:基於物件的快取實作會在每次 set() 時動態配置節點,在高吞吐量工作負載下觸發頻繁的 GC 暫停。 S3-FIFO 透過將快取條目組織成三個輕量級佇列來解決快取污染問題:
  3. 小型 (S):快速篩選單次命中項目(通常約佔總容量的 10%)。
  4. 主要 (M):保存多次存取的高頻項目(約佔容量的 90%)。
  5. 幽靈 (G):記住從小型佇列中淘汰的鍵值,如果重新請求則立即升級至主要佇列。 s3fifo 透過使用連續的 TypedArray(Uint32ArrayFloat64Array)和可重複使用的索引池來支援這些佇列,實現 熱門 get/set 週期中的零動態物件配置。 --- ## v1.0.0 有什麼新功能?(生產就緒) 雖然 v0.1 專注於核心演算法速度,但 v1.0.0 提供了任務關鍵型 Node.js 微服務所需的所有開發人員人體工學、生命週期工具和安全保證。 ### 1. 💾 冷啟動持久性(dumpload) 防止容器重新啟動或部署期間的資料庫雷擊/快取衝撞s3fifo 1.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


連結與回饋

  • 📦 NPMs3fifo
  • 🐙 GitHub 儲存庫BJS-kr/s3fifo 如果您正在尋找 Node.js 中具有掃描抗性和最小 GC 足跡的記憶體內快取替代方案,請試試 s3fifo!非常感謝您的錯誤報告、回饋和 GitHub 星標!🙏