利用Gearman实现并发查询(Multi-Query)

fdabobi 8年前

来自: http://blog.csdn.net//jiao_fuyou/article/details/27170743


这个例子是想从数据库查询出几个结果集,一般的做法是,一个接一个的发送查询,然后汇总结果进行输出。

下面我们利用Gearman的gearman_client_run_tasks实现并发的查询,gearman_client_run_tasks接口可以一次性的提交多个任务,然后在callback函数中异步的处理结果。


PHP的示例如下:

The client:

<?php    $client = new GearmanClient();  $client->addServer();    // initialize the results of our 3 "query results" here  $userInfo = $friends = $posts = null;    // This sets up what gearman will callback to as tasks are returned to us.  // The $context helps us know which function is being returned so we can   // handle it correctly.  $client->setCompleteCallback(function(GearmanTask $task, $context) use (&$userInfo, &$friends, &$posts) {      switch($context) {          case 'lookup_user':              $userInfo = $task->data();              break;          case 'baconate':              $friends = $task->data();              break;          case 'get_latest_posts_by':              $posts = $task->data();              break;      }  });    // Here we queue up multiple tasks to be execute in *as much* parallelism as gearmand can give us  $client->addTask('lookup_user', 'joe@joe.com', 'lookup_user');  $client->addTask('baconate', 'joe@joe.com', 'baconate');  $client->addTask('get_latest_posts_by', 'joe@joe.com', 'get_latest_posts_by');    echo "Fetching...\n";  $start = microtime(true);  $client->runTasks();  $totaltime = number_format(microtime(true) - $start, 2);    echo "Got user info in: $totaltime seconds:\n";  var_dump($userInfo, $friends, $posts);

The worker:

<?php    $worker = new GearmanWorker();  $worker->addServer();    $worker->addFunction('lookup_user', function(GearmanJob $job){      // normally you'd so some very safe type checking and query binding to a database here.      // ...and we're gonna fake that.      sleep(3);      return 'The user requested ('. $job->workload() .') is 7 feet tall and awesome';  });    $worker->addFunction('baconate', function(GearmanJob $job){      sleep(3);      return 'The user ('. $job->workload() .') is 1 degree away from Kevin Bacon';  });    $worker->addFunction('get_latest_posts_by', function(GearmanJob $job){      sleep(3);      return 'The user ('. $job->workload() .') has no posts, sorry!';  });    while ($worker->work());

运行结果:

Fetching...  Got user info in: 9.00 seconds:  string(59) "The user requested (joe@joe.com) is 7 feet tall and awesome"  string(56) "The user (joe@joe.com) is 1 degree away from Kevin Bacon"  string(43) "The user (joe@joe.com) has no posts, sorry!"</span>

发现还是用了9S时间,那是因为只有一个worker,它只能是顺序执行。


一起运行三个worker或更多,再来试试:

Fetching...  Got user info in: 3.00 seconds:  string(59) "The user requested (joe@joe.com) is 7 feet tall and awesome"  string(56) "The user (joe@joe.com) is 1 degree away from Kevin Bacon"  string(43) "The user (joe@joe.com) has no posts, sorry!"</span>


这只是一个并行执行的例子,实际应用中可以有更好的并发性能。