Laravel 分布式应用程序的时间表
Laravel schedules on distributed app
我的应用程序 运行 位于负载平衡器后面的 3 台服务器上。因此它是无状态的,所有数据都存储在redis和MySQL.
如果我的机器 运行 正在运行 artisan cron 调度程序,我假设相同的任务将 运行 3 次。在每台机器上一次,因为不知道它们之间 运行 共享了什么,也就是数据库 table。
解决方案是什么?
edit: In recent versions of Laravel, this is now built-in.
$schedule->command('foo:bar')->onOneServer();
我们在 Artisan 命令中执行此操作,每个 cron 执行应该只 运行 在一台服务器上:
public function handle()
if(!Cache::add(get_class($this), true, 0.5)) {
return false;
}
Cache::add
是同步的,如果密钥已经存在,则 return 为 false,因此即使所有三个服务器都以完全相同的微秒执行,只有一个服务器将继续执行其余任务。
另一个常见选项是仅在集群中的单个服务器上启用 cron,或者为 cron 本身设置专用服务器。
如果您的 Redis 服务器是跨服务器共享的,您可以创建一些逻辑,例如选举领导者应用程序服务器。
您的应用程序逻辑应在处理前检查领导者。示例片段:
if(redis.get("LEADER").equals(currentappserver))
process();
else if(redis.get("LEADER")==null && selectLeader()) -> a lua script call.
process();
由于 redis 是单线程的,因此在 lua 脚本中编写如下代码片段的逻辑:
selectLeader()
if redis.get("LEADER")==null
redis.set("LEADER",current_node)
return true;
else
return false;
它将是原子的,并且始终只有一个领导线程可用。
P.s: 我提供的代码是虚伪的伪代码,不是准确的代码。
Laravel 5.4 支持使用调度器 的多服务器设置(如果升级是一个选项)。
它使用与 ceejayoz 接受的答案类似的方法。
Instead of using the file system to store a lock file, we use the cache store to allow any server to lock/check scheduled events.
我的应用程序 运行 位于负载平衡器后面的 3 台服务器上。因此它是无状态的,所有数据都存储在redis和MySQL.
如果我的机器 运行 正在运行 artisan cron 调度程序,我假设相同的任务将 运行 3 次。在每台机器上一次,因为不知道它们之间 运行 共享了什么,也就是数据库 table。
解决方案是什么?
edit: In recent versions of Laravel, this is now built-in.
$schedule->command('foo:bar')->onOneServer();
我们在 Artisan 命令中执行此操作,每个 cron 执行应该只 运行 在一台服务器上:
public function handle()
if(!Cache::add(get_class($this), true, 0.5)) {
return false;
}
Cache::add
是同步的,如果密钥已经存在,则 return 为 false,因此即使所有三个服务器都以完全相同的微秒执行,只有一个服务器将继续执行其余任务。
另一个常见选项是仅在集群中的单个服务器上启用 cron,或者为 cron 本身设置专用服务器。
如果您的 Redis 服务器是跨服务器共享的,您可以创建一些逻辑,例如选举领导者应用程序服务器。
您的应用程序逻辑应在处理前检查领导者。示例片段:
if(redis.get("LEADER").equals(currentappserver))
process();
else if(redis.get("LEADER")==null && selectLeader()) -> a lua script call.
process();
由于 redis 是单线程的,因此在 lua 脚本中编写如下代码片段的逻辑:
selectLeader()
if redis.get("LEADER")==null
redis.set("LEADER",current_node)
return true;
else
return false;
它将是原子的,并且始终只有一个领导线程可用。
P.s: 我提供的代码是虚伪的伪代码,不是准确的代码。
Laravel 5.4 支持使用调度器 的多服务器设置(如果升级是一个选项)。
它使用与 ceejayoz 接受的答案类似的方法。
Instead of using the file system to store a lock file, we use the cache store to allow any server to lock/check scheduled events.