缓存键未绑定url导致所有标题相同:根源是静态键名(如'key')引发缓存污染,正确做法是用md5($url)生成唯一键如'page_title_'.md5($url),并禁止直接拼接原始url。

在 Laravel 8 中调用 cache()->remember() 抓取多个不同 URL 的页面标题时,若缓存键未与 URL 绑定,所有请求会共用同一缓存值,导致返回的标题全部相同——这不是网络延迟或 HTML 解析失败,而是缓存键设计错误引发的底层数据污染。
问题根源:固定键名导致缓存覆盖
原始写法中使用了完全静态的缓存键:
$pages = cache()->remember('key', now()->addDay(), fn() => file_get_contents($url));
这行代码会让 【所有 URL 请求都写入并读取同一个键 'key'】。系统首次访问 https://example.com 时把它的 title 缓存下来;后续访问 https://laravel.com 或 https://github.com,仍命中 'key',直接返回 example.com 的标题内容。
缓存驱动(如 Redis)不会报错,但数据已彻底错乱——你看到的“标题全一样”,是缓存污染的确定性表现,不是偶发故障。
正确做法:用哈希生成 URL 安全的唯一键
方法一:基础哈希构造(推荐入门)
第一步:对原始 URL 执行 md5() 哈希,生成 32 位合法字符串
第二步:拼接语义化前缀,例如 'page_title_' . md5($url)
第三步:将该键传入 cache()->remember(),确保每个 URL 对应独立缓存槽位
这一步操作起来很简单,直接替换原键名即可生效,无需改动业务逻辑结构。
进阶加固:避免哈希碰撞与参数歧义
方法一:标准化 URL 再哈希
在哈希前先对 URL 做去重参数排序、移除跟踪参数(如 utm_source)、统一协议和末尾斜杠,再调用 md5()。否则 https://a.com/?b=1&a=2 和 https://a.com/?a=2&b=1 会生成两个不同键,造成重复抓取。
方法二:多参数组合时用 JSON 序列化
当缓存依赖 URL + 用户语言 + 设备类型等多维度输入时,先构建关联数组:['url' => $url, 'lang' => $lang, 'device' => $device],再 md5(json_encode($params))。这样能保证键名稳定,不受数组键序影响。
【禁止直接拼接原始 URL 字符串,如 'key-'.$url】——URL 中的空格、问号、井号、斜杠会导致 Redis 拒绝写入,抛出 ERR invalid utf8 string 类异常。











