优化代码

main
gzydong 2021-05-20 16:53:34 +08:00
parent 16ab38200b
commit 3bc0fc69ff
17 changed files with 1068 additions and 1 deletions

View File

@ -0,0 +1,23 @@
<?php
namespace App\Cache\Contracts;
interface HashRedisInterface
{
public function get(string ...$key);
public function add(string $key, string $value);
public function rem(string ...$key);
public function incr(string $member, int $score);
public function count();
public function all();
public function isMember(string $key);
public function delete(string $key);
}

View File

@ -0,0 +1,18 @@
<?php
namespace App\Cache\Contracts;
interface ListRedisInterface
{
public function push(string ...$value);
public function pop();
public function count();
public function clear();
public function all();
public function delete(string $key);
}

View File

@ -0,0 +1,10 @@
<?php
namespace App\Cache\Contracts;
interface LockRedisInterface
{
public function lock(string $key, $lockTime = 1, $timeout = 0);
public function delete(string $key);
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Cache\Contracts;
interface SetRedisInterface
{
public function count();
public function add(string ...$member);
public function rem(string ...$member);
public function isMember(string $member);
public function randMember($count = 1);
public function all();
public function delete(string $key);
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Cache\Contracts;
use Closure;
interface StreamRedisInterface
{
public function add(array $messages, $maxLen = 0, $isApproximate = false);
public function rem(string ...$id);
public function ack(string $group, string $id);
public function count();
public function all();
public function clear();
public function delete();
public function info(string $operation = 'stream');
public function run(Closure $closure, string $group, string $consumer, $count = 1);
}

View File

@ -0,0 +1,16 @@
<?php
namespace App\Cache\Contracts;
interface StringRedisInterface
{
public function set(string $key, string $value, $expires = null);
public function get(string $key);
public function delete(string $key);
public function isExist(string $key);
public function ttl(string $key);
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Cache\Contracts;
interface ZSetRedisInterface
{
public function add(string $member, float $score);
public function rem(string ...$member);
public function incr(string $member, float $score);
public function isMember(string $member);
public function count();
public function all($asc = true, $is_score = true);
public function rank($page = 1, $size = 10, $asc = true);
public function getMemberRank(string $member, $asc = true);
public function getMemberScore(string $member);
public function delete(string $key);
}

View File

@ -0,0 +1,116 @@
<?php
namespace App\Cache\Repository;
use App\Cache\Contracts\HashRedisInterface;
/**
* Redis Hash
*
* @package App\Cache\Repository
*/
class HashRedis implements HashRedisInterface
{
use RedisTrait;
private $prefix = 'rds:hash';
private $name = 'default';
/**
* 获取 Hash
*
* @param string ...$key
* @return array|string
*/
public function get(string ...$key)
{
$func = function ($k) {
return (string)$this->redis()->hGet($this->getKeyName(), $k);
};
if (func_num_args() == 1) return $func($key[0]);
$array = [];
foreach ($key as $arg) {
$array[$arg] = $func($arg);
}
return $array;
}
/**
* 设置 Hash
*
* @param string $key
* @param string $value
*/
public function add(string $key, string $value)
{
$this->redis()->hSet($this->getKeyName(), $key, $value);
}
/**
* 删除 hash
*
* @param string ...$key
* @return bool|int
*/
public function rem(string ...$key)
{
return $this->redis()->hDel($this->getKeyName(), ...$key);
}
/**
* 给指定元素累加值
*
* @param string $member 元素
* @param int $score
* @return float
*/
public function incr(string $member, int $score)
{
return $this->redis()->hincrby($this->getKeyName(), $member, $score);
}
/**
* 获取 Hash 中元素总数
*
* @return int
*/
public function count()
{
return (int)$this->redis()->hLen($this->getKeyName());
}
/**
* 获取 Hash 中所有元素
*
* @return array
*/
public function all()
{
return $this->redis()->hGetAll($this->getKeyName());
}
/**
* 判断 hash 表中是否存在某个值
*
* @param string $key
* @return bool
*/
public function isMember(string $key)
{
return $this->redis()->hExists($this->getKeyName(), $key);
}
/**
* 删除 Hash
*
* @return bool
*/
public function delete()
{
return (bool)$this->redis()->del($this->getKeyName());
}
}

View File

@ -0,0 +1,80 @@
<?php
namespace App\Cache\Repository;
use App\Cache\Contracts\ListRedisInterface;
/**
* Redis List
*
* @package App\Cache\Repository
*/
class ListRedis implements ListRedisInterface
{
use RedisTrait;
private $prefix = 'rds:list';
private $name = 'default';
/**
* Push 队列任务
*
* @param string ...$value
* @return false|int
*/
public function push(string ...$value)
{
return $this->redis()->lPush($this->getKeyName(), ...$value);
}
/**
* 获取队列中的任务
*
* @return bool|mixed
*/
public function pop()
{
return $this->redis()->rPop($this->getKeyName());
}
/**
* 获取列表中元素总数
*
* @return int
*/
public function count()
{
return (int)$this->redis()->lLen($this->getKeyName());
}
/**
* 清除列表中所有元素
*
* @return boolean
*/
public function clear()
{
return $this->redis()->lTrim($this->getKeyName(), 1, 0);
}
/**
* 获取列表中所有元素
*
* @return array
*/
public function all()
{
return $this->redis()->lRange($this->getKeyName(), 0, -1);
}
/**
* 删除 List
*
* @return bool
*/
public function delete()
{
return (bool)$this->redis()->del($this->getKeyName());
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace App\Cache\Repository;
use App\Cache\Contracts\LockRedisInterface;
/**
* Redis Lock
*
* @package App\Cache\Repository
*/
class LockRedis implements LockRedisInterface
{
use RedisTrait;
private $prefix = 'rds:lock';
private $lockValue = 1;
/**
* 获取是毫秒时间戳
*
* @return int
*/
private function time()
{
return intval(microtime(true) * 1000);
}
/**
* 获取 Redis
*
* @param string $key 锁标识
* @param int $lockTime 过期时间/
* @param int $timeout 获取超时/毫秒
* @return bool
*/
public function lock(string $key, $lockTime = 1, $timeout = 0)
{
$lockName = $this->getCacheKey($key);
$start = $this->time();
do {
$lock = $this->redis()->set($lockName, $this->lockValue, ['nx', 'ex' => $lockTime]);
if ($lock || $timeout === 0) {
break;
}
// 默认 0.1 秒一次取锁
usleep(100000);
} while ($this->time() < $start + $timeout);
return $lock;
}
/**
* 释放 Redis
*
* @param string $key
* @return mixed
*/
public function delete(string $key)
{
$script = <<<LAU
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
else
return 0
end
LAU;
return $this->redis()->eval($script, [$this->getCacheKey($key), $this->lockValue,], 1);
}
}

View File

@ -0,0 +1,63 @@
<?php
namespace App\Cache\Repository;
use Hyperf\Redis\Redis;
trait RedisTrait
{
private static $instance;
/**
* 获取单例
*
* @return static
*/
static public function getInstance()
{
if (!(self::$instance instanceof static)) {
self::$instance = new static();
}
return self::$instance;
}
/**
* 获取 Redis 连接
*
* @return Redis|mixed
*/
protected function redis()
{
return redis();
}
/**
* 获取缓存 KEY
*
* @param string $key
* @return string
*/
private function getCacheKey(string $key)
{
return sprintf('%s:%s', trim($this->prefix, ':'), trim($key, ':'));
}
/**
* 获取缓存 KEY
*
* @return string
*/
private function getKeyName()
{
return $this->getCacheKey($this->name);
}
/**
* 加载数据到缓存
*/
public function reload()
{
}
}

View File

@ -0,0 +1,94 @@
<?php
namespace App\Cache\Repository;
use App\Cache\Contracts\SetRedisInterface;
/**
* Redis Set
*
* @package App\Cache\Repository
*/
class SetRedis implements SetRedisInterface
{
use RedisTrait;
private $prefix = 'rds:set';
private $name = 'default';
/**
* 添加集合元素
*
* @param string ...$member
* @return bool|int
*/
public function add(string ...$member)
{
return $this->redis()->sAdd($this->getKeyName(), ...$member);
}
/**
* 删除集合元素
*
* @param string ...$member
* @return int
*/
public function rem(string ...$member)
{
return $this->redis()->sRem($this->getKeyName(), ...$member);
}
/**
* 判断是否是集合元素
*
* @param string $member
* @return bool
*/
public function isMember(string $member)
{
return $this->redis()->sIsMember($this->getKeyName(), $member);
}
/**
* 获取集合中所有元素
*
* @return array
*/
public function all()
{
return $this->redis()->sMembers($this->getKeyName());
}
/**
* 获取集合中元素个数
*
* @return int
*/
public function count()
{
return $this->redis()->scard($this->getKeyName());
}
/**
* 获取随机集合中的元素
*
* @param int $count
* @return array|bool|mixed|string
*/
public function randMember($count = 1)
{
return $this->redis()->sRandMember($this->getKeyName(), $count);
}
/**
* 删除 Set 集合表
*
* @return bool
*/
public function delete()
{
return (bool)$this->redis()->del($this->getKeyName());
}
}

View File

@ -0,0 +1,155 @@
<?php
namespace App\Cache\Repository;
use Closure;
use App\Cache\Contracts\StreamRedisInterface;
class StreamRedis implements StreamRedisInterface
{
use RedisTrait;
private $prefix = 'rds:stream';
private $name = 'default';
/**
* 添加消息
*
* @param array $messages 消息信息
* @param int $maxLen 消息队列最大长度
* @param false $isApproximate
* @return string
*/
public function add(array $messages, $maxLen = 0, $isApproximate = false)
{
return $this->redis()->xAdd($this->getKeyName(), '*', $messages, $maxLen, $isApproximate);
}
/**
* 删除消息
*
* @param string ...$id 消息ID
* @return int
*/
public function rem(string ...$id)
{
return $this->redis()->xDel($this->getKeyName(), $id);
}
/**
* 消费者消息确认
*
* @param string $group 消费组
* @param string $id 消息ID
* @return int
*/
public function ack(string $group, string $id)
{
return $this->redis()->xAck($this->getKeyName(), $group, [$id]);
}
/**
* 获取消息总数
*
* @return int
*/
public function count()
{
return $this->redis()->xLen($this->getKeyName());
}
/**
* 获取所有消息
*
* @return array
*/
public function all()
{
return $this->redis()->xRange($this->getKeyName(), '-', '+');
}
/**
* 清空消息队列
*
* @return bool
*/
public function clear()
{
foreach ($this->all() as $k => $v) {
$this->rem($k);
}
return true;
}
/**
* 删除消息队列 KEY
*
* @return int
*/
public function delete()
{
return $this->redis()->del($this->getKeyName());
}
/**
* 对消息队列进行修剪,限制长度
*
* @param int $maxLen
* @param bool $isApproximate
* @return int
*/
public function trim(int $maxLen, bool $isApproximate = false)
{
return $this->redis()->xTrim($this->getKeyName(), $maxLen, $isApproximate);
}
public function group($operation, $group, $msgId = '', $mkStream = false)
{
return $this->redis()->xGroup($operation, $this->getKeyName(), $group, $msgId, $mkStream);
}
public function pending($group, $start = null, $end = null, $count = null, $consumer = null)
{
return $this->redis()->xPending($this->getKeyName(), $group, $start, $end, $count, $consumer);
}
/**
* 查看队列信息
*
* @param string $operation [stream:队列信息groups:消费组信息]
* @return mixed
*/
public function info(string $operation = 'stream')
{
return $this->redis()->xInfo($operation, $this->getKeyName());
}
/**
* 运行消息队列
*
* @param Closure $closure 闭包函数
* @param string $group 消费组
* @param string $consumer 消费者
* @param int $count 同时获取的任务个数
*/
public function run(Closure $closure, string $group, string $consumer, $count = 1)
{
$this->group('create', $group, '0');
while (true) {
$tasks = $this->redis()->xReadGroup($group, $consumer, [$this->getKeyName() => '>'], $count);
if (empty($tasks)) {
sleep(1);// 获取不到任务,延时一秒
continue;
}
foreach ($tasks[$this->getKeyName()] as $id => $task) {
if ($closure($id, $task)) {
$this->ack($group, $id);
}
}
}
}
}

View File

@ -0,0 +1,74 @@
<?php
namespace App\Cache\Repository;
use App\Cache\Contracts\StringRedisInterface;
/**
* String Cache
*
* @package App\Cache\Repository
*/
class StringRedis implements StringRedisInterface
{
use RedisTrait;
private $prefix = 'rds:string';
/**
* 设置缓存
*
* @param string $key 缓存标识
* @param string $value 缓存数据
* @param null $expires 过期时间
* @return bool
*/
public function set(string $key, string $value, $expires = null)
{
return $this->redis()->set($this->getCacheKey($key), $value, $expires);
}
/**
* 获取缓存数据
*
* @param string $key 缓存标识
* @return false|mixed|string
*/
public function get(string $key)
{
return $this->redis()->get($this->getCacheKey($key));
}
/**
* 删除 String 缓存
*
* @param string $key 缓存标识
* @return bool
*/
public function delete(string $key)
{
return (bool)$this->redis()->del($key);
}
/**
* 判断缓存是否存在
*
* @param string $key 缓存标识
* @return bool
*/
public function isExist(string $key)
{
return (bool)$this->get($key);
}
/**
* 获取缓存过期时间
*
* @param string $key 缓存标识
* @return bool|int
*/
public function ttl(string $key)
{
return $this->redis()->ttl($this->getCacheKey($key));
}
}

View File

@ -0,0 +1,169 @@
<?php
namespace App\Cache\Repository;
use App\Cache\Contracts\ZSetRedisInterface;
/**
* Class ZSetRedis
*
* @package App\Cache\Repository
*/
class ZSetRedis implements ZSetRedisInterface
{
use RedisTrait;
private $prefix = 'rds:zset';
private $name = 'default';
/**
* 添加有序集合元素
*
* @param string $member
* @param float $score
* @return int
*/
public function add(string $member, float $score)
{
return $this->redis()->zAdd($this->getKeyName(), $score, $member);
}
/**
* 删除有序集合元素
*
* @param string ...$member
* @return int
*/
public function rem(string ...$member)
{
return $this->redis()->zRem($this->getKeyName(), ...$member);
}
/**
* 给指定元素累加分数
*
* @param string $member 元素
* @param float $score
* @return float
*/
public function incr(string $member, float $score)
{
return $this->redis()->zIncrBy($this->getKeyName(), $score, $member);
}
/**
* 获取有序集合元素总数
*
* @return int
*/
public function count()
{
return $this->redis()->zCard($this->getKeyName());
}
/**
* 获取有序集合所有元素
*
* @param bool $asc [true:从高到低排序false:从低到高排序]
* @param bool $is_score 是否需要分数值
* @return array
*/
public function all($asc = true, $is_score = true)
{
return $this->redis()->{$asc ? 'zRevRange' : 'zRange'}($this->getKeyName(), 0, -1, $is_score);
}
/**
* 获取排行榜单
*
* @param int $page 分页
* @param int $size 分页大小
* @param bool $asc [true:从高到低排序false:从低到高排序]
* @return array
*/
public function rank($page = 1, $size = 10, $asc = true)
{
$count = $this->count();
[$start, $end] = $asc ? ['+inf', '-inf'] : ['-inf', '+inf'];
$rows = $this->redis()->{$asc ? 'zRevRangeByScore' : 'zRangeByScore'}($this->getKeyName(), $start, $end, [
'withscores' => true,
'limit' => [($page - 1) * $size, $size]
]);
$ranks = [];
foreach ($rows as $node => $score) {
$ranks[] = [
'rank' => $this->getMemberRank($node, $asc),
'node' => $node,
'score' => $score
];
}
return [
'count' => $count,
'page' => $page,
'size' => $size,
'ranks' => $ranks
];
}
/**
* 获取指定区间分数
*
* @param string $start 最低分值
* @param string $end 最高分值
* @param array $options
* @return array
*/
public function range(string $start, string $end, array $options = [])
{
return $this->redis()->zRangeByScore($this->getKeyName(), $start, $end, $options);
}
/**
* 获取指定元素的排名
*
* @param string $member 元素
* @param bool $asc [true:从高到低排序false:从低到高排序]
* @return false|int
*/
public function getMemberRank(string $member, $asc = true)
{
return $this->redis()->{$asc ? 'zRevRank' : 'zRank'}($this->getKeyName(), $member) + 1;
}
/**
* 获取指定元素的分数
*
* @param string $member 元素
* @return bool|float
*/
public function getMemberScore(string $member)
{
return $this->redis()->zScore($this->getKeyName(), $member);
}
/**
* 判断是否是集合元素
*
* @param string $member
* @return bool
*/
public function isMember(string $member)
{
return $this->redis()->zScore($this->getCacheKey($this->name), $member);
}
/**
* 删除 ZSet 有序集合表
*
* @return bool
*/
public function delete()
{
return (bool)$this->redis()->del($this->getKeyName());
}
}

103
app/Command/TestCommand.php Normal file
View File

@ -0,0 +1,103 @@
<?php
declare(strict_types=1);
namespace App\Command;
use App\Cache\Repository\HashRedis;
use App\Cache\Repository\ListRedis;
use App\Cache\Repository\LockRedis;
use App\Cache\Repository\SetRedis;
use App\Cache\Repository\StreamRedis;
use App\Cache\Repository\StringRedis;
use App\Cache\Repository\ZSetRedis;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
use Psr\Container\ContainerInterface;
/**
* @Command
*/
class TestCommand extends HyperfCommand
{
/**
* @var ContainerInterface
*/
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct('test:command');
}
public function configure()
{
parent::configure();
$this->setDescription('Hyperf Demo Command');
}
public function handle()
{
//$lock = LockRedis::getInstance();
//var_dump($lock->delete('ttt'));
//var_dump($lock->lock('ttt', 180));
//$string = StringRedis::getInstance();
//var_dump($string->set('yuandong', 'dong', 30));
//var_dump($string->ttl('yuandong'));
//var_dump($string->isExist('yuandong'));
//$hash = HashRedis::getInstance();
//for ($i = 0; $i < 10; $i++) {
// $hash->add('user:' . $i, (string)rand(0, 100));
//}
//var_dump($hash->count());
//var_dump($hash->all());
//var_dump($hash->isMember('user:1'));
//var_dump($hash->rem('user:3'));
//var_dump($hash->get('user:6'));
//$hash->incr('user:6',11);
//var_dump($hash->get('user:6'));
//$list = ListRedis::getInstance();
//$list->push('1','2','3','4','5');
//var_dump($list->all());
//var_dump($list->clear());
//var_dump($list->count());
//$set = SetRedis::getInstance();
//$set->add('user1','user:2','user:3');
//var_dump($set->all());
//var_dump($set->count());
//var_dump($set->isMember('user:3'));
//var_dump($set->randMember(2));
//$zset = ZSetRedis::getInstance();
//for ($i = 0; $i < 10; $i++) {
// $zset->add('user:' . $i, rand(0, 100));
//}
//var_dump($zset->count());
//var_dump($zset->all());
//var_dump($zset->getMemberScore('user:2'));
//var_dump($zset->getMemberRank('user:2'));
//var_dump($zset->rank());
//var_dump($zset->range('20','60'));
//$stream = StreamRedis::getInstance();
//var_dump($stream->info());
//for ($i = 0; $i < 10; $i++) {
// $stream->add([
// 'user_id' => $i,
// 'time' => time()
// ]);
//}
//
//$stream->run(function (string $id, array $data): bool {
// echo PHP_EOL . " 消息ID: {$id} , 任务数据: " . json_encode($data);
//
// return true;
//}, 'default', 'default');
}
}

View File

@ -226,7 +226,7 @@ class ContactsController extends CController
{ {
$num = ApplyNumCache::get($this->uid()); $num = ApplyNumCache::get($this->uid());
return $this->response->success([ return $this->response->success([
'unread_num' => $num ? $num : 0 'unread_num' => $num ?: 0
]); ]);
} }