Google Apps Script 快取應用實戰|CacheService

更新 發佈閱讀 10 分鐘

副標:用三層快取(記憶體 / CacheService / PropertiesService)大幅降低 API 次數與延遲

問題背景與需求

  • 目標:在 Google Apps Script 中實作快取層,減少重複 API 呼叫與資料庫查詢
  • 限制: CacheService 單筆上限 100 KB 最長有效期 21600 秒(6 小時) ScriptCache / UserCache / DocumentCache 範圍不同
  • 輸出:可複用的 getOrSet() 工具、命名空間化 key、多層快取示範

💡 為什麼我會做這個? 專案中 API 呼叫量逼近上限,且相同請求反覆出現。先用快取減少呼叫與延遲,再談下游優化。

架構與流程

Caller
└─▶ Memory Cache(單次執行內暫存)
├─ 命中 → 回傳
└─ 未命中 → CacheService(Script/User/Document)
├─ 命中 → 回傳 + 回灌 Memory
└─ 未命中 → 呼叫 API/DB
└─ 成功 → 寫入 CacheService + Memory (+ PropertiesService 備援)

環境與版本

  • OS:不限
  • Runtime:Google Apps Script(V8)
  • 套件:無
  • API:CacheService

步驟實作

  1. 檔案與路徑:/gas/cache/cache_util.gs
var __MEM_CACHE__ = {};

function getCacheByScope(scope) {
switch (scope) {
case 'user': return CacheService.getUserCache();
case 'document': return CacheService.getDocumentCache();
default: return CacheService.getScriptCache();
}
}

function makeCacheKey(ns, key) {
return ns + '::' + key;
}

function getOrSet(opts) {
var ns = opts.ns || 'default';
var key = makeCacheKey(ns, opts.key);
var ttl = opts.ttl || 300;
var scope = opts.scope || 'script';
var provider = opts.provider;
var useProps = !!opts.fallbackToProps;

if (__MEM_CACHE__.hasOwnProperty(key)) return __MEM_CACHE__[key];

var cache = getCacheByScope(scope);
var raw = cache.get(key);
if (raw) {
var val = JSON.parse(raw);
__MEM_CACHE__[key] = val;
return val;
}

if (useProps) {
var props = PropertiesService.getScriptProperties();
var pRaw = props.getProperty(key);
if (pRaw) {
try {
var pVal = JSON.parse(pRaw);
cache.put(key, JSON.stringify(pVal), Math.min(ttl, 300));
__MEM_CACHE__[key] = pVal;
return pVal;
} catch (e) {}
}
}

var data = provider();
var json = JSON.stringify(data);
if (json.length <= 100 * 1024) {
cache.put(key, json, Math.min(ttl, 21600));
}
if (useProps && json.length <= 500 * 1024) {
PropertiesService.getScriptProperties().setProperty(key, json);
}
__MEM_CACHE__[key] = data;
return data;
}

function invalidateCache(ns, businessKey, scope) {
var key = makeCacheKey(ns, businessKey);
delete __MEM_CACHE__[key];
(getCacheByScope(scope || 'script')).remove(key);
}
  1. 檔案與路徑:/gas/api/user_api.gs
function fetchUserProfileFromApi(userId) {
var url = 'https://api.example.com/data?uid=' + encodeURIComponent(userId);
var res = UrlFetchApp.fetch(url, { 'muteHttpExceptions': true, 'timeout': 10000 });
if (res.getResponseCode() !== 200) throw new Error('API_ERROR');
return JSON.parse(res.getContentText());
}

function getUserProfile(userId) {
return getOrSet({
ns: 'api:v1:user',
key: 'uid=' + userId,
ttl: 900,
scope: 'script',
fallbackToProps: true,
provider: function () {
return fetchUserProfileFromApi(userId);
}
});
}
  1. 檔案與路徑:/gas/cache/scope_examples.gs
function getUserPrefs(userId) {
return getOrSet({
ns: 'prefs:v1',
key: userId,
ttl: 3600,
scope: 'user',
provider: function () {
return { theme: 'dark', locale: 'zh-TW' };
}
});
}

function getDocMeta() {
return getOrSet({
ns: 'docmeta:v1',
key: 'current',
ttl: 600,
scope: 'document',
provider: function () {
return { title: DocumentApp.getActiveDocument().getName() };
}
});
}

驗證與結果

首次呼叫:820 ms(API 實際請求)
第二次呼叫:12 ms(Memory 命中)
冷啟呼叫:55 ms(CacheService 命中)

常見錯誤與排錯表

訊息/現象 可能原因 解法 Exceeded maximum cache size 單筆超過 100KB 精簡資料、拆分多 key Service invoked too many times 太頻繁存取 CacheService 提高 TTL、加強 Memory 命中 更新後資料沒變 忘記失效快取 呼叫 invalidateCache() Key 打架 無命名空間 使用 ns::key 並加版本號

延伸與 TODO

  • 列表/分頁資料分片快取
  • API 搭配 ETag/Last-Modified 減少資料量
  • 實作批次失效(prefix-based invalidate)

版本資訊(Changelog)

  • 2025-08-14:初稿

工具小筆記|

  • CacheService 三種範圍:Script(專案共享)、User(個人)、Document(綁文件)
  • TTL 建議:易變 1–5 分鐘;一般 10–30 分鐘;低頻資料 1–6 小時
  • Key 建議加版本號(如 api:v1)避免破壞性更新時資料不一致
留言
avatar-img
留言分享你的想法!
avatar-img
麟製所
2會員
30內容數
軟體、旅遊分享
麟製所的其他內容
2025/11/10
七天版旅遊方案 ✈️ 短期旅遊:來台灣 3–7 天旅客 🎒 環島背包客:一週環島行程 🏖️ 長週末度假:連假出遊 👨‍💼 短期出差:一週出差往返不同城市 💡 重點:短期專屬方案,價格優惠,立即兌換即可使用。
2025/11/10
七天版旅遊方案 ✈️ 短期旅遊:來台灣 3–7 天旅客 🎒 環島背包客:一週環島行程 🏖️ 長週末度假:連假出遊 👨‍💼 短期出差:一週出差往返不同城市 💡 重點:短期專屬方案,價格優惠,立即兌換即可使用。
2025/11/07
想升級會員卻不知如何下手?別擔心!本文將詳細教學如何透過 LINE Bot 購買會員方案、收取 Gumroad 寄送的啟用碼,並一步步引導你完成兌換流程,讓你快速升級並立即享有所有會員專屬權益。從標準、進階到旅遊方案,買季卡更划算!常見問題 Q&A 詳盡解答。立即開始升級,體驗完整會員服務!
2025/11/07
想升級會員卻不知如何下手?別擔心!本文將詳細教學如何透過 LINE Bot 購買會員方案、收取 Gumroad 寄送的啟用碼,並一步步引導你完成兌換流程,讓你快速升級並立即享有所有會員專屬權益。從標準、進階到旅遊方案,買季卡更划算!常見問題 Q&A 詳盡解答。立即開始升級,體驗完整會員服務!
2025/11/04
這篇文章分享了我在開發 LINE Bot 設定功能時,發現使用者輸入的冒號與底線雖然外觀相同,但實際上是不同的 Unicode 字元,導致系統無法正確解析。透過撰寫函式,我將全形、特殊變體符號轉換為標準半形符號。文章以簡單比喻讓非工程師也能理解,並附上程式碼與實測結果,適合開發者與一般讀者參考。
Thumbnail
2025/11/04
這篇文章分享了我在開發 LINE Bot 設定功能時,發現使用者輸入的冒號與底線雖然外觀相同,但實際上是不同的 Unicode 字元,導致系統無法正確解析。透過撰寫函式,我將全形、特殊變體符號轉換為標準半形符號。文章以簡單比喻讓非工程師也能理解,並附上程式碼與實測結果,適合開發者與一般讀者參考。
Thumbnail
看更多
你可能也想看
Thumbnail
身為採購專家,當然不能錯過11/11購物節的超殺折扣!本文將帶你深入瞭解蝦皮11/11購物節的完整攻略,從必領的各種優惠券、商城折扣,到限時的搶購技巧,讓你買到手軟荷包也不哭泣。更重要的是,揭密蝦皮分潤計畫,教你如何零成本創業,透過分享商品連結,每月輕鬆加薪,開啟數位遊牧人生!
Thumbnail
身為採購專家,當然不能錯過11/11購物節的超殺折扣!本文將帶你深入瞭解蝦皮11/11購物節的完整攻略,從必領的各種優惠券、商城折扣,到限時的搶購技巧,讓你買到手軟荷包也不哭泣。更重要的是,揭密蝦皮分潤計畫,教你如何零成本創業,透過分享商品連結,每月輕鬆加薪,開啟數位遊牧人生!
Thumbnail
雙11購物節將近,這次分享一些蝦皮海外賣場購物的步驟與注意事項,並且介紹雙11蝦皮購物的相關優惠;另外蝦皮分潤計畫持續招募新血中,只要分享購物連結即可獲得分潤,是很適合創作者的額外收入管道喔!
Thumbnail
雙11購物節將近,這次分享一些蝦皮海外賣場購物的步驟與注意事項,並且介紹雙11蝦皮購物的相關優惠;另外蝦皮分潤計畫持續招募新血中,只要分享購物連結即可獲得分潤,是很適合創作者的額外收入管道喔!
Thumbnail
2025 google 數位人才探索計畫-Google Cloud學程結業證書
Thumbnail
2025 google 數位人才探索計畫-Google Cloud學程結業證書
Thumbnail
Struggling to decide between the current and latest app version on Google Play? This article explains both versions and helps you choose the right one
Thumbnail
Struggling to decide between the current and latest app version on Google Play? This article explains both versions and helps you choose the right one
Thumbnail
不久前,我受到「白飯之亂」的啟發,設計了一堂帶孩子寫評論的文章。。後來,在構思《全國兒童週刊》的專欄文章時,我靈機一動,將這個概念故事化,協助學生在故事中理解評論的要點。
Thumbnail
不久前,我受到「白飯之亂」的啟發,設計了一堂帶孩子寫評論的文章。。後來,在構思《全國兒童週刊》的專欄文章時,我靈機一動,將這個概念故事化,協助學生在故事中理解評論的要點。
Thumbnail
Google Apps Script 的教學要來了!還請多多支持愛護🙏🙏🙏
Thumbnail
Google Apps Script 的教學要來了!還請多多支持愛護🙏🙏🙏
Thumbnail
一直以來都是喜特先生在教學,我們今天來換個角度,看看 Google 官方部落格是怎麼教的!我在那邊找到了一篇關於使用智慧型方塊的好範例,在這分享給大家。
Thumbnail
一直以來都是喜特先生在教學,我們今天來換個角度,看看 Google 官方部落格是怎麼教的!我在那邊找到了一篇關於使用智慧型方塊的好範例,在這分享給大家。
Thumbnail
Apps Script 的 Google Translate Service 可以幫你自動翻譯文本,是個還不錯的翻譯方案。來一起看看我的觀點!
Thumbnail
Apps Script 的 Google Translate Service 可以幫你自動翻譯文本,是個還不錯的翻譯方案。來一起看看我的觀點!
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News