作者:無哲、言合
一、前言:Dify 的規模化挑戰
Dify 是當前最受歡迎的低代碼 LLM 應用開發平台之一,在 Github 上已斬獲 120k+ 的星標數。國內外有眾多企業基於 Dify 構建自己的智能體應用。阿里雲可觀測團隊既是 Dify 的深度用户,也是社區的活躍貢獻者。
在大規模生產實踐中,我們發現 Dify 在高負載場景下面臨顯著的數據庫性能瓶頸:其執行引擎高度依賴 PostgreSQL,單次 Chat 請求可能觸發數百甚至上千次數據庫訪問;與此同時,Worker 進程在知識庫索引構建、Trace 追蹤等任務中也會持續寫入大量數據。這頻繁導致 DB 連接池打滿、慢查詢頻發 等問題,已成為制約 Dify 集羣橫向擴展與併發能力的關鍵瓶頸。
二、現狀與挑戰:Dify 存儲機制痛點分析
數據分佈現狀
Dify 的數據主要分為三類:
- Meta類 數據:租户、應用、工作流、工具等配置信息;
- 運行時日誌:工作流執行明細、會話歷史、消息記錄等;
- 文件類數據:用户上傳文件、知識庫文檔、多模態輸出等(通常存於對象存儲)。
其中Meta 與運行日誌均存儲在 PostgreSQL 中,運行時日誌佔據了數據庫的絕大部分資源。以我們的生產環境為例,運行日誌佔 DB 存儲空間的 95%以上。在訪問頻率最高和慢查詢最多的 SQL 模式中,絕大多數都與運行日誌的讀寫相關。
Dify 的運行日誌包含工作流的執行明細記錄和會話消息數據,執行記錄中有工具輸出、模型上下文等大量長文本信息,並且運行日誌數量也會隨着用户請求快速增長。
核心痛點
將這類海量、高吞吐的日誌數據全量存儲在 PostgreSQL 中,帶來了多重挑戰:
- 負載壓力大: Workflow 節點的每次執行都會產生明細日誌(節點執行明細數據,記錄節點的輸入輸出和運行狀態等數據),高併發下
workflow_node_executions表的讀寫極易成為熱點。 - 連接佔用: 儘管 Dify 1.x 的幾個版本對數據庫長連接問題做了很多優化(如 issue #22307[1]),但日誌密集訪問仍加劇連接池壓力,影響核心業務的連接獲取。
- 擴展性不足: 運行日誌隨着業務量呈爆發式增長,而 PG 擴容依賴垂直升配,升級規格往往伴隨主備切換導致的連接閃斷或維護窗口,難以實現完全的無感擴容。社區已有多個反饋(如 issue #18800 [2]因會話數據堆積導致首 Token 延遲增加 3 秒; issue #22796 [3]呼籲將日誌遷出 PG)
- 分析加工能力缺失: 控制枱僅支持有限關鍵詞檢索,難以滿足業務對歷史會話進行多維分析、二次加工及精細化運營的需求。
社區的積極探索與演進
運行日誌存儲一直是影響 Dify 系統性能與穩定性的痛點。針對這一問題,社區一直在積極尋求解決方案,並已落地了多項優化措施:
- 內存數據庫(issue #20147[4]):適用於無需持久化的輕量場景,同時新版執行引擎已完成日誌存儲抽象,為後續異構存儲改造奠定了基礎。
- 後台異步執行( issue #20050[5]):通過 Celery Worker 異步寫入日誌,有效降低了核心鏈路的延遲,減輕了 API 引擎對 DB 的同步依賴。
- 週期性清理( issue #23399[6]):引入自動清理機制,定期移除陳舊的會話與執行記錄,有效緩解了數據庫存儲膨脹問題。
- 大字段分離存儲: 針對 LLM 長上下文導致的大字段問題,支持將超長字段截斷並轉存至對象存儲,減輕了 DB 的 I/O 壓力。
根因分析:數據特徵與存儲引擎的錯配
上述優化在特定階段非常有效,緩解了 Dify 的燃眉之急,但在大規模生產場景下,應用層的邏輯優化(異步、清理等)已觸及天花板。要徹底解決擴展性問題,必須消除數據特徵與存儲引擎的錯配——即我們一直在試圖用“關係型數據庫”去承載本該由“日誌系統”處理的數據。
Dify 工作流記錄雖然並非完全是Append-Only寫,但具有鮮明的日誌特徵,與典型的業務數據(如用户信息、應用配置)截然不同:
- 終態不可變: 記錄僅在執行期短暫流轉,結束後即成為“只讀”檔案。在 PG 中長期留存海量只讀數據,不僅擠佔昂貴的 SSD 資源,龐大的表數據更會顯著降低索引效率與查詢性能。
- 泛結構化與 Schema 易變: 核心負載為巨大的 JSON 對象(每個工作流節點的Inputs/Outputs),且結構隨版本迭代。PG 難以高效處理深層 JSON 檢索,且億級大表的 DDL 變更會引發長時間鎖表風險。
- 高吞吐時序寫入: 日誌隨時間源源不斷地產生,持續消耗 IOPS 與數據庫連接。請求高峯期極易導致連接池耗盡,導致創建應用等核心業務因資源爭搶而失敗。
因此,我們需要一種支持存算分離、彈性伸縮、低成本且具備原生 OLAP 能力的存儲架構。阿里雲日誌服務(SLS) 憑藉其雲原生特性,成為解決這一瓶頸的最佳選擇。
三、方案選型:為什麼 SLS 更適合 Dify 日誌場景
SLS 並不是“另一個數據庫替代”,它是為日誌場景量身定製的基礎設施。在Dify工作流日誌場景下,相比於 PG,SLS 在以下四個維度實現了架構上的優化升級:
極致彈性,應對流量波動
Dify 業務常有突發流量(如 AI 推理高峯)。PostgreSQL 需按峯值預置硬件資源,低谷期的資源浪費,一旦流量突增超過預設上限,數據庫穩定性會有問題。
而SLS 作為 SaaS 化雲服務,天然支持秒級彈性伸縮,無須關心分片或容量上限,且默認支持 3AZ 同城冗餘。
高寫入吞吐 + 架構解耦,保障核心穩定
- 高併發寫入: SLS 針對日誌場景優化,數據以追加方式順序寫入,避免了數據庫中常見的隨機 I/O 和鎖競爭,能以極低成本支撐數萬 TPS 的寫入吞吐,輕鬆應對 AI 業務的寫入洪峯。
- 資源隔離: 將日誌負載剝離至 SLS 雲端,實現日誌數據流與 Dify 核心業務事務的物理隔離,有效保障主業務系統的穩定性與性能。
海量日誌,低成本長期留存
SLS 數據採用高壓縮比技術,支持自動化分層存儲,可將歷史數據自動沉降至低頻和歸檔存儲,無需維護清理腳本,成本遠低於數據庫 SSD。這使得 Dify 能以極低的成本滿足長週期的分析和審計需求。
開箱即用的數據價值釋放能力
- Schema-on-Read: SLS 寫入時不強制校驗 Schema,完美適配 Dify 快速迭代帶來的字段變更,無需對歷史數據重新變更。
- 秒級分析: SLS 內置了針對日誌優化的分析引擎(倒排索引+列存)。開發者可以使用關鍵詞從海量日誌中檢索,也可以利用 SQL 對億級日誌進行實時聚合分析,將日誌數據轉化為業務洞察。
- 豐富數據生態: 日誌在SLS中,可以進一步進行更完善的處理和分析,比如數據加工清洗、聯合分析、可視化、告警、消費和投遞等等。
四、技術實現:核心架構改造與插件化
為了將 SLS 引入 Dify,整個工程實施分為兩個部分:一是對 Dify 核心的插件化改造,二是基於 SLS 讀寫日誌的插件實現。
1.Dify 核心插件化改造
Dify 早期架構中,工作流記錄的讀寫邏輯深度耦合了 SQLAlchemy(PG ORM),擴展性受限。從 v1.4.1 以後社區引入了 WorkflowExecution 的領域模型(#20067[7])並開始逐步對工作流執行核心流程進行重構,定義了一套標準的 Repository 接口,涵蓋日誌的寫入、更新、讀取以及統計等標準行為。在 v1.8.0 社區引入了 Repository 的異步實現,通過推遲日誌記錄保存提升了工作流執行速度。
雖然 Repository 接口為多存儲驅動提供了可能,但早期的抽象並不徹底:它主要解決了“寫”的抽象,但大量“讀”操作仍繞過 Repository 直接依賴 SQLAlchemy,且複雜的跨表 Join 查詢使得存儲層難以真正剝離。
為此,我們和 Dify 研發團隊多次交流,確定了 Repository 抽象層的完整實現方案。我們通過剝離跨表關聯查詢、標準化讀取與統計接口,真正實現了存儲層的完全解耦與插件化加載。
2.SLS 日誌插件實現
在插件實現過程中,核心挑戰在於抹平關係型數據庫(PG)與日誌系統(SLS)在數據模型上的差異。為此,我們採用了以下技術策略:
基於多版本的狀態管理
SLS 的 LogStore 是 Append-Only 追加寫入,而Dify 的工作流執行過程存在狀態流轉,從 RUNNING 變為 SUCCEEDED/FAIL。因此我們採用了多版本控制的思路:
- 寫入策略:每次狀態更新,不覆蓋舊日誌,而是新寫入一條包含完整狀態的日誌記錄。我們在日誌模型中引入了一個納秒級的時間戳字段
log_version來區分版本。 - 讀取策略:在查詢或統計時,插件內部會生成聚合 SQL,對於同一個
workflow_run_id,始終選取log_version最大的那條記錄作為最終狀態。
Schema 自動同步
Dify 的迭代速度非常快,數據庫模型經常發生變更。如果每次升級 Dify 都需要用户手動維護索引配置,將極大地增加運維負擔。SLS 插件啓動時會自動掃描 SQLAlchemy 模型定義,並與 SLS 索引配置進行 Diff。一旦發現新字段,自動調用 API 更新索引。用户無需手動維護索引,開發者也無須為 SLS 單獨編寫升級腳本。
原生 PG 協議兼容
值得一提的是,SLS 新增原生支持 PostgreSQL 協議。絕大部分原有的統計與分析 SQL,均可通過 PG 兼容模式直接發送到 SLS 上執行,極大地降低了插件的開發適配成本。
五、實踐指南:配置與平滑遷移
該功能已正式合併至 Dify 社區主分支。基於Dify最新代碼,只需進行簡單配置,就可以將工作流執行記錄切換到SLS存儲。
第一步:準備工作
(1)創建 Project:在阿里雲日誌服務控制枱創建 Project(建議與業務同地域)
無需手動創建 Logstore 和索引,Dify 啓動後插件會自動檢測並創建。
(2)獲取訪問憑證:獲取具備 SLS 讀寫權限的 AccessKey ID 和 Secret。
可以授予
AliyunLogFullAccess,或按需配置最小權限(創建/查看Project、創建/查看logstore、創建/更新/查看索引、寫日誌、查日誌等)
第二步:配置Dify
在 .env 或 docker-compose.yaml 中修改以下配置項,將工作流存儲驅動指向 SLS 插件,並補充連接信息:
# 1. 修改 Repository 驅動指向 SLS 插件
CORE_WORKFLOW_EXECUTION_REPOSITORY=extensions.logstore.repositories.logstore_workflow_execution_repository.LogstoreWorkflowExecutionRepository
CORE_WORKFLOW_NODE_EXECUTION_REPOSITORY=extensions.logstore.repositories.logstore_workflow_node_execution_repository.LogstoreWorkflowNodeExecutionRepository
API_WORKFLOW_NODE_EXECUTION_REPOSITORY=extensions.logstore.repositories.logstore_api_workflow_node_execution_repository.LogstoreAPIWorkflowNodeExecutionRepository
API_WORKFLOW_RUN_REPOSITORY=extensions.logstore.repositories.logstore_api_workflow_run_repository.LogstoreAPIWorkflowRunRepository
# 2. 新增 SLS 連接配置
ALIYUN_SLS_ACCESS_KEY_ID=your_access_key_id
ALIYUN_SLS_ACCESS_KEY_SECRET=your_access_key_secret
ALIYUN_SLS_ENDPOINT=cn-hangzhou.log.aliyuncs.com
ALIYUN_SLS_REGION=cn-hangzhou
ALIYUN_SLS_PROJECT_NAME=your_project_name
ALIYUN_SLS_LOGSTORE_TTL=365 # 日誌存儲天數
# 3. 遷移開關配置
LOGSTORE_DUAL_WRITE_ENABLED=false
LOGSTORE_DUAL_READ_ENABLED=true
為了保證存量 PG 用户能平滑升級到 SLS 版本,我們在插件中提供了兩個開關:
(1)雙寫機制:通過配置 LOGSTORE_DUAL_WRITE_ENABLED=True(默認關閉),系統會將日誌同時寫入 PG 和 SLS。這適用於存量用户遷移初期的灰度驗證,確保在不改變原有數據流的情況下,驗證 SLS 的配置正確性和 Dify 版本升級本身的兼容性。
(2)雙讀降級機制:通過配置 LOGSTORE_DUAL_READ_ENABLED=True(默認開啓),系統優先從 SLS 讀取日誌。如果 SLS 中未找到該記錄(例如遷移前的老歷史數據),插件會自動降級回 PG 再次嘗試讀取。
六、成效對比:遷移到SLS的三大收益
收益一:DB壓力顯著下降
切換到SLS,相當於把現有PG中數據量最大的兩張表的數據遷移走了。根據我們線上業務的數據,DB減少了95%以上的存儲空間(運行時間越長,這個比例越高),並且讀寫過程中的DB的連接數、CPU等壓力也有顯著降低。
收益二:存儲成本大幅降低
為了直觀量化遷移後的成本收益,我們以一個典型的生產級場景進行估算:假設 Dify 應用日增日誌 10GB,為了滿足模型評估與回溯需求,需留存最近 300 天(約 3TB)的數據。
注:這裏估算SLS成本的時候,已經將存多條狀態記錄會佔用存儲空間的因素考慮進去。 此外對於PG實際生產中還需額外考慮高可用多副本、預留存儲空間、連接池擴容等隱性成本。
這裏造成近 10 倍成本差距 的根本原因在於存儲機制的不同。
Dify的工作流記錄包含了用户提問、知識召回、工具調用和模型響應等數據,是評估和迴歸等任務需要的數據資產,長期留存價值高。
- 對於 PG: 存儲時間越長,數據量越大,對昂貴的 SSD 存儲空間佔用就越多,成本會大幅增長。pg實例需要提前預估存儲空間,存儲空間不可能完全利用起來,必然閒置一部分空間。
- 對於 SLS: 專為日誌設計的高壓縮比與分層存儲技術,使得存儲數據量越大、時間越長,其邊際成本優勢越明顯。
收益三:數據價值釋放,從“運維監控”到“業務洞察”
這裏我們以一個真實的 Dify 應用場景——“電商智能客服助手”為例,展示日誌數據接入 SLS 後,如何挖掘其背後更大的業務價值。
(1)無縫集成,原生體驗
接入 SLS 後,Dify 界面上的日誌查詢與回溯體驗保持不變,但底層存儲已完全切換。
- 日誌回溯:Dify 控制枱的日誌詳情頁直接從 SLS 讀取數據,響應更迅速。
- 監控圖表:Dify 內置的監控統計圖表,也是通過執行 SLS SQL 實時生成的。
(2)超越基礎,SLS 進階分析
雖然 Dify 內置了基礎查詢和統計功能,但面對複雜的業務分析需求,我們可以直接轉至 SLS 控制枱,解鎖更強大的能力。
- 任意字段的高速檢索
SLS 支持全文索引和任意鍵值對條件的組合查詢,快速精準檢索出符合某種特定特徵的日誌。
- 業務趨勢分析(可視化)場景
比如這裏我們分析“用户意圖識別”這個工作流節點裏,按識別出的用户意圖的分類統計隨時間變化的PV情,便於通過觀察不同分類的趨勢變化,做出相應的運營決策。
* and title: 用户意圖識別 and intent | select json_extract(outputs, '$.intent') as "用户意圖", date_trunc('minute', __time__) t, count(1) as pv group by "用户意圖",t order by t limit all
- 異常診斷(漏斗分析)場景
可以通過漏斗圖,分析觀察工作流哪些中間節點出現異常失敗的比率較高。
status:succeeded | select title, count(distinct workflow_run_id) cnt group by title order by cnt desc
- 成本與風險風控(實時告警)場景
配置告警規則,統計 LLM 節點的 Token 消耗,一旦超過預設閾值,立即觸發釘釘/電話告警。
- 數據閉環(ETL 與加工)場景
利用數據加工和定時 SQL,對工作流的輸入輸出進行清洗、脱敏與標準化,構建持續更新的評估與訓練數據集。
總之,將 Dify 工作流日誌接入 SLS,不僅能高效查詢日誌,更能通過分析、可視化、告警和數據加工,將日誌轉化為業務洞察,真正實現從“看日誌”到“懂業務”的躍升。
七、總結:邁向生產級 AI 架構
將 Dify 運行日誌遷移至阿里雲 SLS,並非一次簡單的“存儲替換”,而是 Dify 向生產級高可用架構演進的關鍵一躍。
我們通過業務數據與日誌數據解耦的架構改造,成功將高吞吐、泛結構化的日誌流從事務型數據庫中剝離。讓 PostgreSQL 專注核心業務事務處理,讓 SLS 充分發揮其在海量數據存儲與分析上的原生優勢。
這一特性帶來的價值是全方位的:
- 解決DB性能瓶頸: 將日誌與核心事務解耦,從根本上解決數據庫瓶頸,保證核心業務穩定性。
- 大幅降低日誌成本: 利用SLS的彈性伸縮、高壓縮比、分層存儲,低成本存儲海量日誌。
- 充分釋放數據價值: 從簡單的日誌查看升級為強大的實時分析、監控告警、加工處理,將運維數據轉換為業務洞察。
如果您正在構建大規模的 AI 應用,或者正被 Dify 數據庫的性能瓶頸所困擾,現在就是升級的最佳時機。擁抱雲原生日誌架構,讓您的 Dify 跑得更快、更穩、更智能。
參考鏈接:
[1]https://github.com/langgenius/dify/issues/22307
[2]https://github.com/langgenius/dify/issues/18800#event-17534118862
[3]https://github.com/langgenius/dify/issues/22796
[4]https://github.com/langgenius/dify/issues/20147
[5]https://github.com/langgenius/dify/pull/20050
[6]https://github.com/langgenius/dify/issues/23399
[7]https://github.com/langgenius/dify/pull/20067