什麼是 Lottery 類別
Illuminate\Support\Lottery 是可將機率式操作以流暢 API 表達的工具類別。可以簡潔地寫出如「每 100 個請求執行 1 次處理」、「僅對部分請求記錄詳細日誌」等模式。
實作位於
src/Illuminate/Support/Lottery.php。Laravel 亦於 Session GC、Cache Lock 的 prune 等框架內部活用此類別。基本用法
以整數比例指定機率
以Lottery::odds($chances, $outOf) 指定「chances 次中選」的機率。
以小數指定機率
省略$outOf 並傳入 0.0〜1.0 的小數,則會直接作為機率使用。
不帶 callback 回傳布林值
若未設定 winner / loser,choose() 中選時回傳 true,未中時回傳 false。
執行多次
若對choose($times) 傳入次數,會回傳結果的陣列。
作為 Callable 傳入
Lottery 實例實作了 __invoke,可直接傳入接受 callable 的 API。
實務使用情境
1. Cache 的 prune(每 100 次僅執行 1 次)
適合刪除過期記錄等無需每次執行的維護處理。2. 遙測、取樣(僅部分請求記錄詳細日誌)
若將所有請求都記錄成本過高,可用於取樣。3. 類似 A/B 測試的行為
以機率將使用者分派至 2 條程式碼路徑。4. 作為 Scheduler 的輔助,隨機執行定期任務
當希望在多台伺服器上避免重複執行且隨機執行某任務時可用。Laravel 框架內的機率模式
Laravel 也於框架內部廣泛使用機率式維護處理。部分實作因為在Lottery 類別新增之前撰寫,直接使用 random_int(),但思維相同。
1
Session:垃圾回收
Illuminate\Session\Middleware\StartSession::configHitsLottery() 使用 config/session.php 的 lottery 設定,以 random_int 進行機率判定並執行 GC。2
DatabaseLock:過期 Lock 的 prune
Illuminate\Cache\DatabaseLock::acquire() 於每次取得 Lock 時以相同比例模式刪除過期 Lock。3
DB::whenQueryingForLongerThan — 傳入 Lottery 類別的範例
因
Lottery 實例可作為 callable 傳入,可直接用於慢查詢偵測的 callback。測試時的使用
具備隨機性的程式碼測試中,可使用Lottery 提供的測試 API。
Lottery::alwaysWin() — 恆使中選
Lottery::alwaysLose() — 恆使未中
Lottery::fix() — 以序列固定結果
可以 true/false 的陣列控制多次呼叫的結果。
Lottery::setResultFactory() — 注入自訂 factory
若需更精細的控制,可使用自訂 factory。
套件開發的活用
於服務提供者註冊
若於套件的服務提供者中組入維護處理,可透過Lottery 分散負載。
從設定值讀取 odds
若允許使用者從設定檔變更機率,會更方便調整。於 Middleware 進行取樣
API 參考
相關頁面
Macroable trait
學習為既有類別新增方法的擴充模式。
Conditionable trait
學習透過
when() / unless() 設計條件分支鏈。