什么是 Lottery 类
Illuminate\Support\Lottery 是可以用流畅 API 描述基于概率操作的工具类。它可以简洁地表达「每 100 个请求执行一次」「只对部分请求记录详细日志」这类模式。
实现位于
src/Illuminate/Support/Lottery.php。Laravel 也在框架内部使用它,例如 Session GC、缓存锁的清理。基本用法
用整数比率指定概率
Lottery::odds($chances, $outOf) 指定「chances 次」的概率。
用小数指定概率
省略$outOf 而传入 0.0〜1.0 的小数时,会直接作为概率使用。
无回调时返回布尔值
若未设置 winner / loser,choose() 会返回:中奖时 true,未中时 false。
多次执行
给choose($times) 传入次数会返回结果数组。
作为 Callable 传入
Lottery 实例实现了 __invoke,因此可以直接作为 callable 传入。
实战用例
1. 缓存清理(每 100 次执行一次)
对于删除过期记录这类不需要每次都执行的维护处理非常合适。2. 遥测采样(只对部分请求记录详细日志)
若对所有请求记日志成本过高,可以用它做采样。3. A/B 测试式的行为切换
概率性地把用户分配到两条不同的代码路径。4. 作为 Scheduler 的辅助随机执行定时任务
在多台服务器中避免重复执行的同时随机执行某个任务时可以使用。Laravel 框架内部的概率模式
Laravel 在框架内部广泛使用了概率式维护处理。其中一些实现是在Lottery 类被加入之前编写的,因此直接使用 random_int(),但思路是一致的。
1
Session:垃圾回收
Illuminate\Session\Middleware\StartSession::configHitsLottery() 使用 config/session.php 中的 lottery 配置,通过 random_int 概率判定并执行 GC。2
DatabaseLock:清理过期锁
Illuminate\Cache\DatabaseLock::acquire() 在每次获取锁时以相同比率清理过期锁。3
DB::whenQueryingForLongerThan — 传入 Lottery 类的示例
Lottery 实例可作为 callable 传入,可直接用于慢查询检测回调。测试时的用法
对包含随机性的代码测试,可使用Lottery 提供的测试用 API。
Lottery::alwaysWin() — 始终中奖
Lottery::alwaysLose() — 始终未中
Lottery::fix() — 用序列固定结果
可用 true/false 数组控制多次调用的结果。
Lottery::setResultFactory() — 注入自定义 Factory
如需更细粒度的控制,可使用自定义 Factory。
在包开发中的应用
在 Service Provider 中注册
在包 Service Provider 中集成维护处理时,可用Lottery 分散负载。
从配置读取赔率
允许通过配置文件调整概率,方便用户微调。在 Middleware 中做采样
API 参考
相关页面
Macroable trait
学习向既有类添加新方法的扩展模式。
Conditionable trait
学习基于
when() / unless() 的条件分支链式设计。