跳到內容
OmniRoute source

Redis Production Configuration Guide (中文 (繁體))

設定 值 所在位置
REDIS_URL 環境變數 redis://redis:6379(compose),選用 rateLimiter.ts:5、.env.example
REDIS_KEY_PREFIX 環境變數 omniroute:(預設) rateLimiter.ts、redisQuotaStore.ts、redisCircuitBreakerStore.ts、.env.example
QUOTA_STORE_REDIS_URL 環境變數 獨立設定,可與 REDIS_URL 不同 quota/storeFactory.ts
QUOTA_STORE_DRIVER "sqlite"(預設),可選用 "redis" quota/storeFactory.ts
ioredis maxRetriesPerRequest 3 rateLimiter.ts 用戶端建立作業
enableReadyCheck 未設定(ioredis 預設值:true) —
lazyConnect 未設定(ioredis 預設值:false) —
retryStrategy 未設定(ioredis 預設值:200ms 基準、指數成長) —
TLS/密碼/資料庫索引 未設定 —
Sentinel/Cluster 未設定——僅支援獨立單一節點 —

OmniRoute 會與主機上執行的其他服務共用 Redis 執行個體。若沒有命名空間,auth:api_key:<sha256> 或 rl:* 等鍵可能會與使用同一 Redis 的其他應用程式所建立的鍵發生衝突(此執行個體在 127.0.0.1:6379 上執行 Redis,並與其他服務並存)。

將 REDIS_KEY_PREFIX 設為非空字串,為 OmniRoute 的每一個鍵加上前綴:

Terminal window
# .env——所有 OmniRoute 鍵都會變成 omniroute:rl:*、omniroute:auth:*、omniroute:quota:*、omniroute:warmup:cb:*
REDIS_KEY_PREFIX=omniroute:
  • 預設值: omniroute:(當 REDIS_KEY_PREFIX 未設定或為空白時套用)。
  • **套用範圍:**速率限制器與驗證快取(透過 keyPrefix 共用 ioredis 用戶端)、配額儲存區(KEY_PREFIX = "${REDIS_KEY_PREFIX}quota"),以及預熱斷路器(KEY_PREFIX = "${REDIS_KEY_PREFIX}warmup:cb:")。
  • 當 Redis 中已存在鍵時,變更前綴會使舊鍵成為孤立鍵(它們會透過 TTL/LRU 到期)。此變更是安全的,無需移轉。唯一的例外是標示為禁止之連線的預熱斷路器鍵:該鍵會在沒有 TTL 的情況下持久保存,因此請使用 redis-cli --scan --pattern '<old-prefix>warmup:cb:*' 列出遺留鍵並將其刪除。
  • ioredis keyPrefix 會在寫入時自動加上前綴,並在讀取時將其移除,因此應用程式碼永遠不會看到該前綴。

1. 連線池/用戶端選項(ioredis Redis 建構函式)

Section titled “1. 連線池/用戶端選項(ioredis Redis 建構函式)”

目前的程式碼建立單一 new Redis(url),且未指定任何自訂選項。對於正式環境的多副本部署,請在程式碼中傳入用戶端工廠函式,或包裝 getRedisClient():

const redis = new Redis(REDIS_URL, {
maxRetriesPerRequest: null, // 不限制重試次數;由 retryStrategy 決定
enableReadyCheck: true, // 接受呼叫前確認伺服器已就緒
lazyConnect: true, // 建構時不連線;等待第一次呼叫
retryStrategy: (times) => {
if (times > 10) return null; // 重試 10 次後放棄 → 稍後重新連線
return Math.min(times * 200, 5000); // 200ms、400ms、…,上限 5s
},
enableAutoPipelining: true, // 將並行命令合併為一次 TCP 寫入
keepAlive: 10000, // 每 10s 執行一次 TCP keep-alive
});

主要權衡:

  • maxRetriesPerRequest: null + retryStrategy — 建議用於正式環境,避免 Redis 暫時重新啟動時立即導致所有請求失敗。checkRateLimit() 中的記憶體內備援會承接失敗路徑。
  • lazyConnect: true — 避免伺服器在開始接受連線前,於啟動階段依賴 Redis 必須已經上線。
  • enableAutoPipelining: true — 減少並行速率限制檢查的往返次數;單一連線超過 50 RPS 時特別有益。
# 記憶體
maxmemory 80% # 為作業系統頁面快取保留空間
maxmemory-policy allkeys-lru # 在記憶體壓力下淘汰過期未用的驗證快取項目
# 持久化(選用 — OmniRoute 即使不使用持久化也可安全應對當機)
save 300 1 # 若至少有 1 個鍵變更,則至少每 5 分鐘建立一次快照
appendonly no # 不需要 AOF;資料可重新產生
appendfsync no # 無 fsync 額外負擔(RDB 已足夠)
# 網路
timeout 0 # 不因閒置而中斷連線
tcp-keepalive 300 # 5 分鐘 keep-alive
tcp-backlog 511 # 因應突發負載的連線待處理佇列
# 效能
hz 10 # 預設值;對延遲敏感時使用 100
activedefrag yes # 碎片率 >10% 時自動重組

maxmemory-policy allkeys-lru 的權衡: 在記憶體壓力下,驗證快取項目可能被淘汰。這是安全的 — setCachedApiKey 總會在快取未命中時重新填入資料,而 SQLite 備援則是權威資料來源。速率限制器的 Lua 指令碼會建立體積小且依設計存續時間很短的鍵。

正式環境的 compose(docker-compose.prod.yml)使用 redis:8.6.2-alpine。請新增:

redis:
image: redis:8.6.2-alpine
command:
[
"redis-server",
"--maxmemory",
"512mb",
"--maxmemory-policy",
"allkeys-lru",
"--activedefrag",
"yes",
"--save",
"300 1",
]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
start_period: 5s

所有副本共用單一 Redis — 速率限制器的 Lua 指令碼依賴單一權威鍵空間。若各副本使用多個 Redis 執行個體,將失去原子性,並使配額加倍。所有應用程式副本都應使用單一 Redis(或具備容錯移轉功能的 Redis Sentinel 叢集)。

連線數: 每個應用程式副本會開啟 2 個 TCP 連線至 Redis(速率限制器用戶端 + 配額儲存區用戶端)。10 個副本 → 20 個連線,遠低於預設 Redis 執行個體的 10k 連線上限。

透過健康檢查端點公開:

// src/app/api/monitoring/health/route.ts 已呼叫速率限制器函式
// 新增 Redis 專用檢查:
// 1. 透過 ioredis .ping() 檢查 PING 延遲
// 2. 透過 INFO memory 檢查記憶體用量
// 3. 透過 INFO clients 檢查連線數
// 4. maxmemory-policy 的命中率(evicted_keys / keyspace_hits)

應關注的主要指標:

  • 每秒淘汰的鍵數 — 若持續不為零,請提高 maxmemory
  • 遭封鎖的用戶端 — 非零表示 Lua 指令碼執行緩慢或競爭情況嚴重
  • 遭拒絕的連線 — 已達連線上限;僅有 20 個連線時很少發生

flowchart LR
subgraph App["應用程式副本"]
RL[rateLimiter.ts]
AK[apiKeys.ts]
QS[redisQuotaStore.ts]
end
RL -- "REDIS_URL" --> R1[(Redis\n共用)]
AK -- "重複使用 RL 的用戶端" --> R1
QS -- "QUOTA_STORE_REDIS_URL" --> R2[(Redis\n配額儲存區)]
R1 --> R2 -- "可以是相同執行個體" --> R1

檔案 用途
src/shared/utils/rateLimiter.ts 主要 Redis 用戶端、Lua 速率限制指令碼、記憶體內備援
src/lib/db/apiKeys.ts 驗證快取 — Redis→SQLite 備援
src/lib/quota/redisQuotaStore.ts 用於選用配額儲存區的獨立 Redis 用戶端
src/lib/quota/storeFactory.ts 在 sqlite 與 redis 配額驅動程式之間切換
docker-compose.prod.yml 正式環境 Redis 容器(映像檔 redis:8.6.2-alpine)
.env.example Redis 環境變數文件
src/app/api/local/redis/ 用於開發容器協調管理的 API 路由
bin/cli/commands/redis.mjs 用於開發容器協調管理的 CLI 命令

OmniRoute 原始碼 (a58000c7685f)

HagiCode

HagiCode 是智慧代理程式開發工作台,結合結構化工作流程、多代理程式執行與 Hero Dungeon 介面,將想法化為交付成果。

以更聰明、更快速且更有趣的智慧代理程式工作流程,打造實用的軟體。

HagiCode 淺色主題介面畫面
  • Smart結構化流程將意圖轉化為從構想到交付的可執行步驟。
  • Efficient多代理程式工作流程讓研究、實作與審查並行進行。
  • FunHero Dungeon 讓長時間的程式協作更直覺、更有參與感。
造訪 HagiCode