UserLogProgressTracking.md 5.2 KB

用户日志系统进度追踪机制优化

概述

根据用户要求,用户日志系统的进度追踪机制已从使用缓存存储改为通过读取 user_logs 表的数据来确定处理进度。这种方式更加可靠和准确。

修改内容

1. 进度追踪方式变更

原来的方式(使用缓存):

// 从缓存获取进度
$lastProcessedId = Cache::get("user_log_collector:last_processed_id:{$sourceTable}", 0);
$lastProcessedTimestamp = Cache::get("user_log_collector:last_processed_timestamp:{$sourceTable}", 0);

// 更新进度到缓存
Cache::put("user_log_collector:last_processed_id:{$sourceTable}", $id, 86400);
Cache::put("user_log_collector:last_processed_timestamp:{$sourceTable}", $timestamp, 86400);

现在的方式(读取user_logs表):

// 从user_logs表获取最后处理的记录
$lastLog = UserLog::where('source_table', $sourceTable)
    ->where('source_type', $sourceType)
    ->orderBy('source_id', 'desc')
    ->first();

$lastProcessedId = $lastLog ? $lastLog->source_id : 0;

2. 核心修改文件

BaseLogCollector.php

  • getLastProcessedId(): 改为从user_logs表查询最后处理的source_id
  • getLastProcessedTimestamp(): 改为从user_logs表查询最后处理的时间戳
  • updateLastProcessedId(): 不再需要手动更新,进度自动追踪
  • updateLastProcessedTimestamp(): 不再需要手动更新,进度自动追踪
  • 添加 getOriginalRecordTimestamp() 抽象方法

各收集器实现

  • FundLogCollector: 添加 getOriginalRecordTimestamp() 方法
  • ItemLogCollector: 添加 getOriginalRecordTimestamp() 方法
  • FarmLogCollector: 添加 getOriginalRecordTimestamp() 方法,处理多表情况

CollectUserLogsCommand.php

  • 修改统计功能,从user_logs表读取进度信息
  • 修改重置功能,清空user_logs表而不是清除缓存
  • 优化错误处理和异常捕获

3. 优势

3.1 数据一致性

  • 进度信息直接来源于实际处理结果
  • 避免缓存与实际数据不一致的问题
  • 重启服务后进度不会丢失

3.2 可靠性

  • 不依赖缓存系统的稳定性
  • 数据持久化存储,不会因为缓存清理而丢失
  • 可以通过数据库查询验证处理进度

3.3 可追溯性

  • 可以查看具体的处理历史
  • 便于问题排查和数据审计
  • 支持按时间范围查询处理记录

4. 实现细节

4.1 进度查询逻辑

protected function getLastProcessedId(): int
{
    try {
        $lastLog = \App\Module\Game\Models\UserLog::where('source_table', $this->sourceTable)
            ->where('source_type', $this->sourceType)
            ->orderBy('source_id', 'desc')
            ->first();

        return $lastLog ? $lastLog->source_id : 0;
    } catch (\Exception $e) {
        Log::error("获取最后处理ID失败", [
            'collector' => $this->collectorName,
            'source_table' => $this->sourceTable,
            'error' => $e->getMessage()
        ]);
        return 0;
    }
}

4.2 农场收集器特殊处理

由于农场收集器需要处理多个表(farm_harvest_logs 和 farm_upgrade_logs),进度查询逻辑特殊处理:

protected function getLastProcessedId(): int
{
    try {
        // 查询农场相关的最后处理记录
        $lastLog = \App\Module\Game\Models\UserLog::where('source_type', $this->sourceType)
            ->whereIn('source_table', ['farm_harvest_logs', 'farm_upgrade_logs'])
            ->orderBy('source_id', 'desc')
            ->first();

        return $lastLog ? $lastLog->source_id : 0;
    } catch (\Exception $e) {
        return 0;
    }
}

4.3 时间戳获取

protected function getOriginalRecordTimestamp(int $recordId): int
{
    try {
        $record = FundLogModel::find($recordId);
        return $record ? $record->create_time : 0;
    } catch (\Exception $e) {
        return 0;
    }
}

5. 计划任务配置

routes/console.php 中添加了用户日志收集的计划任务:

// 每分钟收集用户日志(实现高频收集)
\Illuminate\Support\Facades\Schedule::command('game:collect-user-logs --limit=100')->everyMinute();

虽然无法实现严格的"每2秒"执行,但每分钟执行可以保证较高的实时性。

6. 命令使用

# 显示收集器信息
php artisan game:collect-user-logs --info

# 显示统计信息
php artisan game:collect-user-logs --stats

# 执行收集(限制处理记录数)
php artisan game:collect-user-logs --limit=100

# 显示详细处理过程
php artisan game:collect-user-logs --detail

# 重置进度(清空user_logs表)
php artisan game:collect-user-logs --reset

7. 注意事项

  1. 重置功能: --reset 选项会清空整个user_logs表,请谨慎使用
  2. 性能考虑: 每次查询user_logs表获取进度,在高频执行时需要注意数据库性能
  3. 兼容性: 保留了原有的缓存相关方法,确保向后兼容
  4. 错误处理: 增强了异常处理,避免单个收集器失败影响整体流程

总结

通过这次优化,用户日志系统的进度追踪更加可靠和准确。系统不再依赖缓存存储进度信息,而是直接从实际的处理结果(user_logs表)中获取进度,确保了数据的一致性和可靠性。