基于Laravel应用监控Redis Key变更并在仪表盘展示方案咨询
嘿,针对你这个Laravel仪表盘同步Redis告警设备集合的需求,我整理了几个实用的方案,你可以根据自己的架构和实时性要求来选:
方案一:Redis键空间通知 + Laravel事件/广播(实时同步首选)
这个方案利用Redis原生的键空间通知功能,当device:alarming这个SET有增减操作时,主动触发通知,Laravel监听后同步更新仪表盘,能做到近乎实时的效果。
步骤1:开启Redis键空间通知
首先得让Redis支持键事件通知,修改你的Redis配置文件(redis.conf),找到notify-keyspace-events这一行,改成:
notify-keyspace-events "KEA"
K代表监听键空间事件,E代表监听键事件,A代表监听所有类型的事件。如果想更精准,可以改成K$(只监听SET相关操作),不过先开全量更稳妥。
改完后重启Redis服务,或者用命令临时生效(重启后会失效):
redis-cli CONFIG SET notify-keyspace-events "KEA"
步骤2:Laravel里实现Redis订阅监听
创建一个Artisan命令来持续监听Redis的通知频道:
php artisan make:command RedisAlarmingDeviceListener
然后修改命令的逻辑:
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\Redis; class RedisAlarmingDeviceListener extends Command { protected $signature = 'redis:listen-alarming-devices'; protected $description = '监听Redis中device:alarming集合的变更'; public function handle() { $redis = Redis::connection(); // 订阅db0中device:alarming键的所有变更事件(db号根据你的配置调整) $channel = '__keyspace@0__:device:alarming'; $this->info('开始监听device:alarming集合的变更...'); $redis->subscribe([$channel], function ($message, $channel) { // $message就是触发的Redis命令,比如sadd、srem、del等 $this->info("收到变更事件: {$message}"); // 触发Laravel事件,交给监听器处理同步逻辑 event(new \App\Events\AlarmingDevicesUpdated()); }); } }
步骤3:创建事件和监听器
先创建事件:
php artisan make:event AlarmingDevicesUpdated
然后创建处理更新的监听器:
php artisan make:listener UpdateAlarmingDevicesDashboard --event=AlarmingDevicesUpdated
修改监听器的handle方法,同步缓存并推送前端更新:
<?php namespace App\Listeners; use App\Events\AlarmingDevicesUpdated; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Support\Facades\Redis; use Illuminate\Support\Facades\Cache; class UpdateAlarmingDevicesDashboard implements ShouldQueue { // 标记为队列任务,避免阻塞Redis订阅进程 use \Illuminate\Queue\InteractsWithQueue; public function handle(AlarmingDevicesUpdated $event) { // 获取最新的告警设备ID列表 $alarmingDevices = Redis::smembers('device:alarming'); // 缓存最新数据,仪表盘直接读缓存减少Redis请求 Cache::put('alarming_devices', $alarmingDevices, now()->addMinutes(5)); // 推送实时更新到前端(需要Laravel Echo配合) broadcast(new \App\Events\AlarmingDevicesBroadcast($alarmingDevices)); } }
别忘了在app/Providers/EventServiceProvider.php里注册事件和监听器:
protected $listen = [ \App\Events\AlarmingDevicesUpdated::class => [ \App\Listeners\UpdateAlarmingDevicesDashboard::class, ], ];
步骤4:前端实时更新(可选)
如果要让仪表盘自动刷新,用Laravel Echo配合广播事件。先创建广播事件:
php artisan make:event AlarmingDevicesBroadcast
修改广播事件:
<?php namespace App\Events; use Illuminate\Broadcasting\Channel; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class AlarmingDevicesBroadcast implements ShouldBroadcast { use Dispatchable, SerializesModels; public $alarmingDevices; public function __construct($alarmingDevices) { $this->alarmingDevices = $alarmingDevices; } public function broadcastOn() { // 用公开频道,不需要认证 return new Channel('alarming-devices'); } }
前端用Echo监听并更新DOM:
// 初始化Echo后监听频道 Echo.channel('alarming-devices') .listen('AlarmingDevicesBroadcast', (event) => { updateAlarmingDevicesList(event.alarmingDevices); }); function updateAlarmingDevicesList(devices) { const list = document.getElementById('alarming-devices-list'); list.innerHTML = ''; devices.forEach(deviceId => { const item = document.createElement('li'); item.textContent = `告警设备ID: ${deviceId}`; list.appendChild(item); }); }
步骤5:守护监听进程
这个Artisan命令需要持续运行,用Supervisor或者Systemd来守护,比如Supervisor配置:
[program:laravel-redis-alarm-listener] process_name=%(program_name)s command=php /path/to/your/project/artisan redis:listen-alarming-devices autostart=true autorestart=true user=www-data stdout_logfile=/path/to/your/project/storage/logs/redis-listener.log stderr_logfile=/path/to/your/project/storage/logs/redis-listener-error.log
方案二:定时轮询Redis(简单易实现,适合低频率变更场景)
如果你的Redis环境不能修改配置,或者对实时性要求不高,定时轮询是个省心的选择。
步骤1:创建轮询任务
php artisan make:job CheckAlarmingDevicesChanges
修改任务逻辑:
<?php namespace App\Jobs; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Facades\Redis; use Illuminate\Support\Facades\Cache; class CheckAlarmingDevicesChanges implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function handle() { $currentDevices = Redis::smembers('device:alarming'); $cachedDevices = Cache::get('alarming_devices', []); // 对比当前数据和缓存数据,有变化才更新 if ($currentDevices !== $cachedDevices) { Cache::put('alarming_devices', $currentDevices, now()->addMinutes(5)); broadcast(new \App\Events\AlarmingDevicesBroadcast($currentDevices)); } } }
步骤2:注册调度任务
在app/Console/Kernel.php里添加定时任务:
protected function schedule(Schedule $schedule) { // 每10秒轮询一次,可根据需求调整频率 $schedule->job(new \App\Jobs\CheckAlarmingDevicesChanges())->everyTenSeconds(); }
记得开启Laravel的调度器(用Cron或者Supervisor):
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
注意事项
- 性能考量:如果
device:alarming变更非常频繁,建议把事件处理放到队列里(监听器实现ShouldQueue),避免阻塞Redis订阅进程。 - Redis权限:确保Laravel应用的用户有Redis的订阅权限,以及进程运行用户有权限读写项目文件。
- 缓存策略:仪表盘优先读缓存,避免每次请求都直接查Redis,提升响应速度。
内容的提问来源于stack exchange,提问作者Adnan Shahriar
相关产品推荐
相关产品推荐

