<blockquote class="danger">由于无法参悟各worker间如何共享一个class或者全局变量(如channel不在全局变量上就无法进行消息投递),故用Swoole\Table代替.若有人知道如何共享,请不吝告知,谢谢!</blockquote>
<blockquote class="danger">每个worker都是拥有独立的App实体,所以instance到App内是无效的.</blockquote>
<blockquote class="danger">service也是无效的,虽然在启动的时候共用了一个,但是在worker启动后就会被私有化,因此数据也是不通的.</blockquote>
`app\service`目录下新建
<details>
<summary>Atomic.php</summary>
~~~
<?php
namespace app\service;
use think\swoole\Table;
/**
* Class Atomic
* @package app\service
* Waring 数据存于内存中,如果服务重启数据会丢失,注意离线存储,仅做示例参考.
*/
class Atomic
{
private $atomoc;
public function __construct(Table $table)
{
//取得table
$this->atomoc = $table->get('vote');
}
//检查是否存在
private function check(string $uid): void
{
if ($this->atomoc->exist($uid) == false) {
$this->set($uid);
}
}
//创建一个参与者
public function set(string $uid): void
{
// $this->atomoc->set($uid, ['poll' => 0,'icon'=>'']);
$this->atomoc->set($uid, ['poll' => 0]);
}
//票数自增-Table->incr属于原子操作,并发安全.
public function add(string $uid, int $step = 1): int
{
$this->check($uid);
return $this->atomoc->incr($uid, 'poll', $step);
}
//票数自减
public function sub(string $uid, int $step = 1): int
{
$this->check($uid);
return $this->atomoc->decr($uid, 'poll', $step);
}
//获取票数
public function get(string $uid): int
{
$this->check($uid);
return $this->atomoc->get($uid, 'poll');
}
//移除参与者
public function cancelled(string $uid): void
{
if ($this->atomoc->exist($uid)) {
$this->atomoc->del($uid);
}
}
//获取所有参与者,并降序.
public function all(): array
{
$data = [];
foreach ($this->atomoc as $uid => $item) {
$data[$uid] = $this->atomoc->get($uid);
}
arsort($data);
return $data;
}
}
~~~
</details>
在`controller`中使用
~~~
public function index(Atomic $atomic)
{
if ($this->request->param('vote')) {
$atomic->add((string)rand(1, 5));
$atomic->add((string)rand(1, 5), 2);
$atomic->add((string)rand(1, 5), rand(1, 10));
dump($atomic->all());
}
}
~~~
<blockquote class="danger">服务重启数据会丢失,注意离线存储!!!</blockquote>
访问结果如下
![](https://img.kancloud.cn/e8/ee/e8eea6cdc9f122ac7834cdddee3f7cf0_386x271.png)