安全场景应只用random_int()和random_bytes(),二者调用系统加密随机源、无全局状态、线程安全;mt_rand()和rand()共享全局梅森旋转状态,存在种子泄露和结果可预测风险,不适用于密码学或防作弊场景。

PHP 7 中生成随机数字本身是线程安全的,但关键要看你用的是哪个函数。
random_int() 和 random_bytes() 是线程安全的
这两个函数直接调用操作系统级加密随机源(如 /dev/urandom、getrandom() 或 Windows 的 CNG API),底层不依赖全局状态,也不加锁。每次调用都是独立的系统调用,无论并发多少请求,都不会互相干扰或阻塞。
- 适合高并发游戏服、API 服务中生成 token、session_id、抽卡判定等
- PHP 8.4+ 已移除异常抛出逻辑(仅在熵源彻底失效时 fatal,现实中几乎不会发生)
- 无需手动加锁或隔离,可放心在多进程/多线程 Swoole 或 PHP-FPM 场景中使用
mt_rand() 和 rand() 不是真正线程安全的
它们共享一个全局的梅森旋转(Mt19937)状态。在传统 Apache mod_php(多线程模式)或某些 Swoole 配置下,多个请求可能读写同一随机数生成器实例,导致序列被意外推进、结果可预测。
- 即使没显式调用
mt_srand(),不同请求间也可能相互影响 - 种子一旦被猜中或泄露(比如通过爆破 php_mt_seed),整段随机序列可被复现
- 不适合用于密码、密钥、防作弊逻辑等安全敏感场景
注意运行环境的实际线程模型
PHP 本身默认是非线程安全(NTS)构建的,大多数生产环境(如 Nginx + PHP-FPM)采用多进程模型,此时 mt_rand() 的“线程不安全”影响较小——因为每个子进程有独立内存空间。但若你用的是线程安全(TS)版 PHP(如旧版 Apache worker MPM),问题就真实存在。
- 判断方式:运行
php -i | grep "Thread Safety",输出enabled即为 TS 模式 - 即便在 NTS 环境,若业务层用
mt_srand(固定值)初始化,仍会破坏随机性 - 游戏服常见误区:用
mt_rand()做掉落权重判定,被外挂批量采样后逆向出种子,从而预判稀有掉落
简单结论:安全场景只用 random_int() / random_bytes()
不要为了性能妥协安全性。生成 100 万个 random_int(1, 6) 在现代服务器上耗时不到 0.2 秒,远低于数据库或 Redis 的 IO 开销。真正的瓶颈从来不在随机函数本身,而在你拿随机数去干什么。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











