缓存读取报错:unserialize(): Error at offset 2 of 24544 bytes
所属功能组件
缓存(cache)
ThinkPHP 版本
v6.1.4
操作系统
Debian11
错误信息
[code] => 8
[message] => unserialize(): Error at offset 2 of 24544 bytes
[file] => /www/wwwroot/[project]/vendor/topthink/framework/src/think/cache/Driver.php
[line] => 262
错误所在片段
/**
* 反序列化数据
* @access protected
* @param string $data 缓存数据
* @return mixed
*/
protected function unserialize($data)
{
if (is_numeric($data)) {
return $data;
}
$unserialize = $this->options['serialize'][1] ?? "unserialize";
return $unserialize($data);
}
其它说明
或许是因为cache数据量过大,但是没有设置缓存的报错提示。时而出现,暂不确定解决方案
参考解决方案:
1、可以考虑改用json
<?php
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
return [
// 默认缓存驱动
'default' => env('cache.driver', 'file'),
// 缓存连接方式配置
'stores' => [
'file' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 86400 * 7,
// 缓存标签前缀
'tag_prefix' => 'tag:',
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => ['json_encode', 'json_decode'],
],
]
];
2、自定义函数,重新封装下序列化函数
<?php
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
function myUnserialize(...$vars) {
try {
return unserialize(...$vars);
} catch(\Throwable $e) {
return null;
}
}
return [
// 默认缓存驱动
'default' => env('cache.driver', 'file'),
// 缓存连接方式配置
'stores' => [
'file' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 86400 * 7,
// 缓存标签前缀
'tag_prefix' => 'tag:',
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => ['serialize', 'myUnserialize'],
],
]
];
框架层面感觉可以捕抓到异常时,删除缓存,然后返回默认值。但这样会导致开发者不知道这块有异常(自定义序列化机制时)
支持,框架层面可以处理一下。增加一个配置项,当读取缓存错误时,是抛出源异常还是视为缓存数据不存在。 我在使用workerman多进程,使用到数据库和缓存这部分时,经常遇到这个报错,有时候刚启动项目会有出错。改用redis也不会有改善。
我也遇到过这个问题 经过调试发现问题出在vendor\topthink\framework\src\think\cache\driver\Redis.php. 不同进程用同一个hander就会出现, 所以临时修改增加 static protected array $instance = []; //redis实例化时静态变量,防止fork多进程后数据污染
https://github.com/top-think/framework/commit/5ee69f53eb519aae874c7e48b97c61b3998a7e3b