Laravel安排在分布式应用程序上

问题描述 投票:4回答:3

我的应用程序在负载均衡器后面的3台服务器上运行。因此它是无状态的,所有数据都存储在redis和MySQL中。

如果我的机器正在运行工匠cron调度程序,我假设相同的任务将运行3次。一旦在每台机器上,因为不知道它们之间共享的是什么,也就是数据库表。

有什么解决方案?

php laravel redis distributed
3个回答
6
投票

编辑:在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是同步的,如果密钥已经存在则将返回false,因此即使所有三个服务器都以完全相同的微秒执行,也只有一个服务器将继续执行其余任务。

另一个常见选项是在集群中的单个服务器上启用cron,或者为cron本身设置专用服务器。


2
投票

如果您的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:我提供的代码是模糊的伪代码而不是确切的代码。


0
投票

如果升级是一个选项,Laravel 5.4支持使用调度程序进行多服务器设置。

它采用了与ceejayoz接受的答案类似的方法。

我们使用缓存存储来允许任何服务器锁定/检查预定事件,而不是使用文件系统来存储锁文件。

https://github.com/laravel/internals/issues/69

© www.soinside.com 2019 - 2024. All rights reserved.