Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

缓存读取报错:unserialize(): Error at offset 2 of 24544 bytes #3056

Open
cffycls opened this issue Sep 6, 2024 · 4 comments
Open
Labels

Comments

@cffycls
Copy link

cffycls commented Sep 6, 2024

所属功能组件

缓存(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数据量过大,但是没有设置缓存的报错提示。时而出现,暂不确定解决方案

@cffycls cffycls added the bug label Sep 6, 2024
@big-dream
Copy link
Contributor

参考解决方案:

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'],
        ],
    ]
];

@big-dream
Copy link
Contributor

框架层面感觉可以捕抓到异常时,删除缓存,然后返回默认值。但这样会导致开发者不知道这块有异常(自定义序列化机制时)

@big-dream big-dream linked a pull request Sep 14, 2024 that will close this issue
@augushong
Copy link

支持,框架层面可以处理一下。增加一个配置项,当读取缓存错误时,是抛出源异常还是视为缓存数据不存在。
我在使用workerman多进程,使用到数据库和缓存这部分时,经常遇到这个报错,有时候刚启动项目会有出错。改用redis也不会有改善。

@xieyongfa123
Copy link
Contributor

我也遇到过这个问题 经过调试发现问题出在vendor\topthink\framework\src\think\cache\driver\Redis.php. 不同进程用同一个hander就会出现, 所以临时修改增加 static protected array $instance = []; //redis实例化时静态变量,防止fork多进程后数据污染
微信截图_20241007115518

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants