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

时间:2016-06-30 12:45:04

标签: php laravel redis distributed

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

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

有哪些解决方案?

3 个答案:

答案 0 :(得分: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本身提供专用服务器。

答案 1 :(得分: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:我提供的代码是vauge伪代码,而不是确切的代码。

答案 2 :(得分:0)

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

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

  

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

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