Laravel Job的failed方法中访问Redis数据出现异常输出
Laravel Job failed方法中Redis命令返回异常(llen返回字符串、hgetall报类型错误)
问题场景
开发Laravel应用时,在Job的failed方法中尝试读取Redis的列表和哈希数据,出现异常:
- 调用
llen返回字符串timestamp而非预期的数字 - 调用
hgetall触发类型错误:array_values(): Argument #1 ($array) must be of type array, string given
相关代码
public function failed($exception = null): void { // ... if (Redis::exists($this->redisFileKey)) { $fileCount = Redis::llen($this->redisFileKey); Log::info("File count: " . $fileCount); } $orderDetails = Redis::hgetall($this->redisMainDataKey); Log::info("Order details: " . var_export($orderDetails, true)); // ... }
错误日志
[2024-03-22 19:44:13] local.INFO: File count: timestamp [2024-03-22 19:44:13] local.ERROR: array_values(): Argument #1 ($array) must be of type array, string given {"exception":"[object] (TypeError(code: 0): array_values(): Argument #1 ($array) must be of type array, string given at /var/www/html/vendor/predis/predis/src/Command/Redis/HGETALL.php:35)
已通过Redis Insight确认对应键的类型为列表和哈希。
排查与解决方案
1. 验证键名与Redis数据库一致性
- 先打印键的实际值,确认是否指向预期的键:
Log::info('Redis File Key: ' . $this->redisFileKey); Log::info('Redis Main Data Key: ' . $this->redisMainDataKey); - 检查当前Redis连接的数据库,确认与存储数据时的DB一致:
Log::info('Current Redis DB: ' . Redis::connection()->getDb()); - 用Redis CLI直接验证键的类型和值:
# 检查键存在性与类型 redis-cli EXISTS your_file_key redis-cli TYPE your_file_key redis-cli EXISTS your_main_data_key redis-cli TYPE your_main_data_key # 直接执行命令验证结果 redis-cli LLEN your_file_key redis-cli HGETALL your_main_data_key
2. 确认Redis连接实例一致性
如果存储数据时使用了自定义Redis连接(而非默认连接),读取时必须使用相同连接:
// 存储时用自定义连接 Redis::connection('cache')->lpush($this->redisFileKey, 'data'); // failed方法中也要用相同连接读取 $fileCount = Redis::connection('cache')->llen($this->redisFileKey);
同时检查队列配置的Redis连接,确保与数据存储的Redis配置一致。
3. 排查Job属性序列化问题
Job的属性会被序列化后存入队列,可能在反序列化过程中被篡改:
- 在
handle方法和failed方法中分别打印$this->redisFileKey、$this->redisMainDataKey,对比值是否一致 - 确保这些属性没有在构造函数之外被修改
4. 添加类型检查规避异常
在调用Redis命令前先验证键的类型,避免错误:
$fileKeyType = Redis::type($this->redisFileKey); Log::info('File Key Type: ' . $fileKeyType); if ($fileKeyType === 'list' && Redis::exists($this->redisFileKey)) { $fileCount = Redis::llen($this->redisFileKey); Log::info("File count: " . $fileCount); } $mainKeyType = Redis::type($this->redisMainDataKey); Log::info('Main Data Key Type: ' . $mainKeyType); if ($mainKeyType === 'hash') { $orderDetails = Redis::hgetall($this->redisMainDataKey); Log::info("Order details: " . var_export($orderDetails, true)); }
内容的提问来源于stack exchange,提问作者Rupesh Bhandari
相关产品推荐
相关产品推荐

