优化代码

main
gzydong 2021-05-25 18:20:55 +08:00
parent 270f8c2ff7
commit 8476214e12
7 changed files with 130 additions and 24 deletions

View File

@ -4,7 +4,7 @@ namespace App\Cache\Contracts;
interface LockRedisInterface interface LockRedisInterface
{ {
public function lock(string $key, $lockTime = 1, $timeout = 0); public function lock(string $key, $expired = 1, int $timeout = 0);
public function delete(string $key); public function delete(string $key);
} }

View File

@ -3,6 +3,8 @@
namespace App\Cache\Repository; namespace App\Cache\Repository;
use App\Cache\Contracts\LockRedisInterface; use App\Cache\Contracts\LockRedisInterface;
use Swoole\Coroutine;
use Exception;
/** /**
* Redis Lock * Redis Lock
@ -13,40 +15,33 @@ class LockRedis extends AbstractRedis implements LockRedisInterface
{ {
protected $prefix = 'rds-lock'; protected $prefix = 'rds-lock';
protected $lockValue = 1; protected $value = 1;
/**
* 获取是毫秒时间戳
*
* @return int
*/
private function time()
{
return intval(microtime(true) * 1000);
}
/** /**
* 获取 Redis * 获取 Redis
* *
* @param string $key 锁标识 * @param string $key 锁标识
* @param int $lockTime 过期时间/ * @param int $expired 过期时间/
* @param int $timeout 获取超时/ * @param int $timeout 获取超时/秒,默认每隔 0.1 秒获取一次锁
* @return bool * @return bool
*/ */
public function lock(string $key, $lockTime = 1, $timeout = 0) public function lock(string $key, $expired = 1, int $timeout = 0)
{ {
$lockName = $this->getCacheKey($key); $lockName = $this->getCacheKey($key);
$start = $this->time(); // 重复获取次数
$retry = $timeout > 0 ? intdiv($timeout * 100, 10) : 1;
do { do {
$lock = $this->redis()->set($lockName, $this->lockValue, ['nx', 'ex' => $lockTime]); $lock = $this->redis()->set($lockName, $this->value, ['nx', 'ex' => $expired]);
if ($lock || $timeout === 0) { if ($lock || $timeout === 0) {
break; break;
} }
// 默认 0.1 秒一次取锁 // 默认 0.1 秒一次取锁
usleep(100000); Coroutine::getCid() ? Coroutine::sleep(0.1) : usleep(100000);
} while ($this->time() < $start + $timeout);
$retry--;
} while ($retry);
return $lock; return $lock;
} }
@ -67,6 +62,31 @@ class LockRedis extends AbstractRedis implements LockRedisInterface
end end
LAU; LAU;
return $this->redis()->eval($script, [$this->getCacheKey($key), $this->lockValue], 1); return $this->redis()->eval($script, [$this->getCacheKey($key), $this->value], 1);
}
/**
* 获取锁并执行
*
* @param \Closure $closure 闭包函数
* @param string $lock_name 锁名
* @param int $expired 过期时间/
* @param int $timeout 获取超时/
* @return bool
* @throws Exception
*/
public function try(\Closure $closure, string $lock_name, int $expired = 1, int $timeout = 0)
{
if (!$this->lock($lock_name, $expired, $timeout)) return false;
try {
call_user_func($closure);
} catch (Exception $e) {
throw $e;
} finally {
$this->delete($lock_name);
}
return true;
} }
} }

View File

@ -49,9 +49,9 @@ class TestCommand extends HyperfCommand
public function handle() public function handle()
{ {
//$lock = LockRedis::getInstance(); $lock = LockRedis::getInstance();
//var_dump($lock->delete('ttt')); //var_dump($lock->delete('ttt'));
//var_dump($lock->lock('ttt', 180)); //var_dump($lock->lock('ttt', 180, 5));
//$string = StringRedis::getInstance(); //$string = StringRedis::getInstance();
//var_dump($string->set('yuandong', 'dong', 30)); //var_dump($string->set('yuandong', 'dong', 30));

View File

@ -9,12 +9,13 @@ use Hyperf\HttpServer\Annotation\RequestMapping;
/** /**
* 测试相关控制器 * 测试相关控制器
* @Controller() * @Controller()
*
* @package App\Controller * @package App\Controller
*/ */
class TestController extends AbstractController class TestController extends AbstractController
{ {
/** /**
* @RequestMapping(path="indexss", methods="get") * @RequestMapping(path="index", methods="get")
*/ */
public function index() public function index()
{ {

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace App\Process;
use Hyperf\Process\AbstractProcess;
use Hyperf\Process\Annotation\Process;
/**
* @Process(name="RedisExpiredSubscribe")
*/
class RedisExpiredSubscribe extends AbstractProcess
{
public function handle(): void
{
redis()->psubscribe(['__keyevent@5__:expired'], [$this, 'subscribe']);
}
/**
* 过期键回调处理
*
* @param $redis
* @param $pattern
* @param $chan
* @param $msg
*/
public function subscribe($redis, $pattern, $chan, $msg)
{
echo "Pattern: $pattern\n";
echo "Channel: $chan\n";
echo "Payload: $msg\n\n";
}
public function isEnable($server): bool
{
return false;
}
}

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace App\Process;
use Hyperf\Process\AbstractProcess;
use Hyperf\Process\Annotation\Process;
/**
* @Process(name="RedisSubscribe")
*/
class RedisSubscribe extends AbstractProcess
{
/**
* 订阅的通道
*
* @var string[]
*/
private $chans = ['websocket'];
public function handle(): void
{
redis()->subscribe($this->chans, [$this, 'subscribe']);
}
/**
* 订阅处理逻辑
*
* @param $redis
* @param string $chan
* @param string $msg
*/
public function subscribe($redis, string $chan, string $msg)
{
echo PHP_EOL . "chan : $chan , msg : $msg";
}
public function isEnable($server): bool
{
return false;
}
}

View File

@ -23,5 +23,8 @@ return [
'heartbeat' => -1, 'heartbeat' => -1,
'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60), 'max_idle_time' => (float) env('REDIS_MAX_IDLE_TIME', 60),
], ],
'options' => [
\Redis::OPT_READ_TIMEOUT => -1,
],
], ],
]; ];