Yoru Karu Studio
程式設計學習筆記 | 生活心得程式設計學習筆記 | 生活心得
連接池配置不當可能導致「連接不足」或「資源浪費」。如何計算合適的池大小?CONN_MAX_AGE 應該設多少秒?PgBouncer 的三種池模式該如何選擇?
本文將提供完整的連接池配置指南,包括參數計算公式、不同場景的推薦配置,以及生產環境的調優實踐。
Django 默認沒有連接池,但從 1.6 版本開始引入了 CONN_MAX_AGE 持久連接特性。這是連接池嗎?它與真正的連接池有什麼區別?
本文將深入分析 Django 連接管理的演進歷史,對比 django-db-connection-pool 和 PgBouncer 等方案,並提供生產環境的選型建議。
很多人以為「連接數據庫」是瞬間完成的操作,實際上建立一次連接可能需要 20-100 毫秒。在高並發場景下,沒有連接池的 Django 應用會浪費大量時間在重複建立、關閉連接上。
本文將深入分析數據庫連接的真實成本,以及為什麼連接池是生產環境的必備組件。
一、核心差異比較 1.1 設計目標 Celery:分布式任務隊列
解決問題:異步執行耗時任務,避免阻塞主應用 核心特性:任務調度、延遲執行、定時任務 通訊模式:單向(Producer → Worker) 結果返回:通過 Result Backend 查詢 Channels:實時雙向通訊框架
解決問題:實時雙向通訊需求(WebSocket、SSE) 核心特性:持久連接、實時推送、雙向通訊 通訊模式:雙向(Client ↔ Server) 結果返回:即時推送給連接的客戶端 1.2 技術架構對比 ┌─────────────────────────────────────────────────────────┐ │ Celery 架構 │ ├─────────────────────────────────────────────────────────┤ │ │ │ Django View │ │ │ │ │ ├─► task.delay() ─────► Message Broker │ │ │ (Redis/RabbitMQ) │ │ │ │ │ │ │ ▼ │ │ │ Celery Worker │ │ │ │ │ │ │ ▼ │ │ └─► get result ◄──── Result Backend │ │ (Redis/DB) │ │ │ └─────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────┐ │ Channels 架構 │ ├─────────────────────────────────────────────────────────┤ │ │ │ WebSocket Client │ │ │ │ │ ├──► ws:// connect ─► ASGI Server │ │ │ (Daphne/Uvicorn) │ │ │ │ │ │ │ ▼ │ │ │ Consumer │ │ │ │ │ │ │ ▼ │ │ ◄──── push message ◄── Channel Layer │ │ (Redis) │ │ │ └─────────────────────────────────────────────────────────┘1.
什麼是空間複雜度? 空間複雜度(Space Complexity)描述了演算法執行時所需的記憶體空間如何隨著輸入規模增長。它回答了一個關鍵問題:「當資料量變大時,程式需要多少記憶體?」
為什麼空間複雜度很重要? # 情境:處理一個 10GB 的檔案 # 方法 1:全部載入記憶體(可能造成記憶體不足) def process_file_v1(filename): with open(filename, 'r') as f: content = f.read() # 需要 10GB 記憶體! return content.upper() # 方法 2:逐行處理(記憶體使用量固定) def process_file_v2(filename): result = [] with open(filename, 'r') as f: for line in f: # 一次只載入一行 result.append(line.upper()) return ''.join(result) # 方法 3:串流處理(最省記憶體) def process_file_v3(filename, output_filename): with open(filename, 'r') as f_in, open(output_filename, 'w') as f_out: for line in f_in: f_out.write(line.upper())空間複雜度的組成 1. 輸入空間 演算法輸入資料佔用的空間(通常不計入額外空間)。
什麼是時間複雜度? 時間複雜度(Time Complexity)是用來描述演算法執行時間如何隨著輸入規模增長的數學模型。簡單來說,它回答了一個問題:「當資料量變大時,程式會跑多久?」
為什麼需要時間複雜度? 想像你要從一本電話簿中找到某個人的電話號碼:
# 方法 1:從頭翻到尾(線性搜尋) def linear_search(phone_book, name): for entry in phone_book: if entry.name == name: return entry.phone return None # 方法 2:利用排序特性(二分搜尋) def binary_search(phone_book, name): left, right = 0, len(phone_book) - 1 while left <= right: mid = (left + right) // 2 if phone_book[mid].name == name: return phone_book[mid].phone elif phone_book[mid].name < name: left = mid + 1 else: right = mid - 1 return None當電話簿有 1000 個號碼時,差異可能不明顯。但如果有 100 萬個號碼呢?這就是為什麼我們需要時間複雜度分析。