利用Gearman实现并发查询(Multi-Query)
这个样例是想从数据库查询出几个结果集,一般的做法是,一个接一个的发送查询,然后汇总结果进行输出。
The worker:
执行结果:
发现还是用了9S时间,那是由于仅仅有一个worker,它仅仅能是顺序运行。
以下我们利用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>
这仅仅是一个并行运行的样例,实际应用中能够有更好的并发性能。