|
|
@@ -1,9 +1,12 @@
|
|
|
<?php namespace Dever\Helper;
|
|
|
+
|
|
|
use Dever\Debug;
|
|
|
+
|
|
|
class Redis
|
|
|
{
|
|
|
private static $handle;
|
|
|
private static $expire = 3600;
|
|
|
+
|
|
|
public static function connect()
|
|
|
{
|
|
|
if (!self::$handle) {
|
|
|
@@ -11,67 +14,86 @@ class Redis
|
|
|
if (!$config) {
|
|
|
\Dever::error('redis error');
|
|
|
}
|
|
|
+
|
|
|
self::$expire = $config['expire'];
|
|
|
self::$handle = new \Redis;
|
|
|
self::$handle->pconnect($config["host"], $config["port"]);
|
|
|
- if (isset($config['password']) && $config['password']) {
|
|
|
+
|
|
|
+ if (!empty($config['password'])) {
|
|
|
self::$handle->auth($config['password']);
|
|
|
}
|
|
|
+
|
|
|
self::$handle->setOption(\Redis::OPT_READ_TIMEOUT, -1);
|
|
|
}
|
|
|
return self::$handle;
|
|
|
}
|
|
|
+
|
|
|
+ /** -------------------------
|
|
|
+ * KV 基础操作
|
|
|
+ * ------------------------ */
|
|
|
public static function get($key)
|
|
|
{
|
|
|
- return Debug::add(self::connect()->get($key), 'cache');
|
|
|
+ return self::connect()->get($key);
|
|
|
}
|
|
|
+
|
|
|
public static function set($key, $value, $expire = 0)
|
|
|
{
|
|
|
self::expire($expire);
|
|
|
return self::connect()->set($key, $value, self::$expire);
|
|
|
}
|
|
|
+
|
|
|
+ public static function del($key)
|
|
|
+ {
|
|
|
+ return self::connect()->del($key);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** -------------------------
|
|
|
+ * 分布式锁
|
|
|
+ * ------------------------ */
|
|
|
public static function lock($key, $value, $expire = 0)
|
|
|
{
|
|
|
self::expire($expire);
|
|
|
return self::connect()->set($key, $value, ['NX', 'EX' => $expire]);
|
|
|
}
|
|
|
+
|
|
|
public static function unlock($key, $value)
|
|
|
{
|
|
|
- $script = <<< EOF
|
|
|
+ $script = <<<LUA
|
|
|
if redis.call("get", KEYS[1]) == ARGV[1] then
|
|
|
return redis.call("del", KEYS[1])
|
|
|
else
|
|
|
return 0
|
|
|
end
|
|
|
- EOF;
|
|
|
- return self::connect()->eval($script, [$key, $value], 1);
|
|
|
+LUA;
|
|
|
+ return self::connect()->eval($script, [$key, $value], 1);
|
|
|
}
|
|
|
+
|
|
|
+ /** -------------------------
|
|
|
+ * 自增自减
|
|
|
+ * ------------------------ */
|
|
|
public static function incr($key, $value = false)
|
|
|
{
|
|
|
- if ($value) {
|
|
|
- return self::connect()->incrby($key, $value);
|
|
|
- }
|
|
|
- return self::connect()->incr($key);
|
|
|
+ return $value ? self::connect()->incrBy($key, $value) : self::connect()->incr($key);
|
|
|
}
|
|
|
+
|
|
|
public static function decr($key, $value = false)
|
|
|
{
|
|
|
- if ($value) {
|
|
|
- return self::connect()->decrby($key, $value);
|
|
|
- }
|
|
|
- return self::connect()->decr($key);
|
|
|
+ return $value ? self::connect()->decrBy($key, $value) : self::connect()->decr($key);
|
|
|
}
|
|
|
+
|
|
|
+ /** -------------------------
|
|
|
+ * 列表队列
|
|
|
+ * ------------------------ */
|
|
|
public static function push($key, $value)
|
|
|
{
|
|
|
return self::connect()->lpush($key, $value);
|
|
|
}
|
|
|
+
|
|
|
public static function pop($key)
|
|
|
{
|
|
|
$data = self::connect()->brPop($key, 10);
|
|
|
if ($data) {
|
|
|
- if (isset($data[1])) {
|
|
|
- $data = $data[1];
|
|
|
- }
|
|
|
- return $data;
|
|
|
+ return $data[1] ?? $data;
|
|
|
} else {
|
|
|
$pong = self::connect()->ping();
|
|
|
if ($pong != '+PONG') {
|
|
|
@@ -81,47 +103,125 @@ class Redis
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
public static function len($key)
|
|
|
{
|
|
|
- return self::connect()->llen($key);
|
|
|
+ return self::connect()->lLen($key);
|
|
|
}
|
|
|
+
|
|
|
+ /** -------------------------
|
|
|
+ * Hash 操作
|
|
|
+ * ------------------------ */
|
|
|
public static function hGet($key, $hkey = false)
|
|
|
{
|
|
|
if ($hkey) {
|
|
|
- return Debug::add(self::connect()->hGet($key, $hkey), 'cache');
|
|
|
- } else {
|
|
|
- return Debug::add(self::connect()->hGetAll($key), 'cache');
|
|
|
+ return self::connect()->hGet($key, $hkey);
|
|
|
}
|
|
|
+ return self::connect()->hGetAll($key);
|
|
|
}
|
|
|
+
|
|
|
public static function hDel($key, $hkey)
|
|
|
{
|
|
|
return self::connect()->hDel($key, $hkey);
|
|
|
}
|
|
|
+
|
|
|
public static function hExists($key, $hkey)
|
|
|
{
|
|
|
return self::connect()->hExists($key, $hkey);
|
|
|
}
|
|
|
+
|
|
|
public static function hKeys($key)
|
|
|
{
|
|
|
return self::connect()->hKeys($key);
|
|
|
}
|
|
|
- public static function hSet($key, $hkey, $value, $expire = 0)
|
|
|
- {
|
|
|
- self::expire($expire);
|
|
|
- return self::connect()->hKeys($key, $hkey, $value, self::$expire);
|
|
|
- }
|
|
|
- public static function delete($key)
|
|
|
- {
|
|
|
- return self::connect()->delete($key, 0);
|
|
|
- }
|
|
|
+
|
|
|
+ public static function hSet($key, $hkey, $value)
|
|
|
+ {
|
|
|
+ $res = self::connect()->hSet($key, $hkey, $value);
|
|
|
+ return $res;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static function hMSet($key, $value)
|
|
|
+ {
|
|
|
+ $res = self::connect()->hMSet($key, $value);
|
|
|
+ return $res;
|
|
|
+ }
|
|
|
+
|
|
|
+ # 原子操作
|
|
|
+ public static function hOper($key, $field, $amount)
|
|
|
+ {
|
|
|
+ $lua = <<<LUA
|
|
|
+ local balance = redis.call("HGET", KEYS[1], KEYS[2])
|
|
|
+ local change = tonumber(ARGV[1])
|
|
|
+
|
|
|
+ if not balance then
|
|
|
+ return -1
|
|
|
+ end
|
|
|
+
|
|
|
+ balance = tonumber(balance)
|
|
|
+ local new_balance = balance + change
|
|
|
+
|
|
|
+ if new_balance < 0 then
|
|
|
+ return 0
|
|
|
+ end
|
|
|
+
|
|
|
+ redis.call("HSET", KEYS[1], KEYS[2], new_balance)
|
|
|
+ return new_balance
|
|
|
+ LUA;
|
|
|
+
|
|
|
+ return self::connect()->eval($lua, [$key, $field, $amount], 2);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static function oper($key, $amount)
|
|
|
+ {
|
|
|
+ $lua = <<<LUA
|
|
|
+ local balance = redis.call("GET", KEYS[1])
|
|
|
+ local change = tonumber(ARGV[1])
|
|
|
+
|
|
|
+ if not balance then
|
|
|
+ return -1 --余额未初始化
|
|
|
+ end
|
|
|
+
|
|
|
+ balance = tonumber(balance)
|
|
|
+ local new_balance = balance + change
|
|
|
+
|
|
|
+ if new_balance < 0 then
|
|
|
+ return 0 --余额不足
|
|
|
+ end
|
|
|
+
|
|
|
+ redis.call("SET", KEYS[1], new_balance)
|
|
|
+ return new_balance
|
|
|
+ LUA;
|
|
|
+
|
|
|
+ return self::connect()->eval($lua, [$key, $amount], 1);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static function xAdd($key, $col, $value)
|
|
|
+ {
|
|
|
+ return self::connect()->xAdd($key, $col, $value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static function xRead($search, $num, $time)
|
|
|
+ {
|
|
|
+ return self::connect()->xRead($search, $num, $time);
|
|
|
+ }
|
|
|
+
|
|
|
+ /** -------------------------
|
|
|
+ * 关闭连接
|
|
|
+ * ------------------------ */
|
|
|
public static function close()
|
|
|
{
|
|
|
return self::connect()->close();
|
|
|
}
|
|
|
+
|
|
|
+ /** -------------------------
|
|
|
+ * 设置过期
|
|
|
+ * ------------------------ */
|
|
|
private static function expire($expire)
|
|
|
{
|
|
|
if ($expire) {
|
|
|
self::$expire = $expire;
|
|
|
}
|
|
|
}
|
|
|
-}
|
|
|
+}
|