BaseConnection.php 26.9 KB
<?php namespace common\components\redis;

use yii\base\Component;
use yii\helpers\Inflector;
use common\components\redis\transaction\MultiExec as MultiExecTransaction;

/**
 * ----------适配器目前不考虑支持的方\\START-------------
 * 一、"yii-redis" 和 "php redis"  的异同:
 * -CLIENT-
 * 1.在 "yii-redis" 中,方法分别为: clientKill(),clientList(),clientGetname(),clientSetname(),
 * 2.在 "php redis"  中,统一为 client()输入参数的方式
 * [
 *      'CLIENT KILL', // ip:port -Server(服务器)- 关闭地址为 ip:port 的客户端连接。
 *      'CLIENT LIST', // -Server(服务器)- 以人可读的格式,返回所有连接到服务器的客户端信息和统计数据。
 *      'CLIENT GETNAME', // -Server(服务器)- 返回 CLIENT SETNAME 命令为连接设置的名字。因为新创建的连接默认是没有名字的, 对于没有名字的连接, CLIENT GETNAME 返回空白回复。
 *      'CLIENT SETNAME', // -Server(服务器)- 为当前连接分配一个名字。 这个名字会显示在 CLIENT LIST 命令的结果中, 用于识别当前正在与服务器进行连接的客户端。
 * ]
 * -CONFIG-
 * 1.在 "yii-redis" 中,方法分别为: configGet(),configSet(),configResetstat(),
 * 2.在 "php redis"  中,统一为 config()输入参数的方式
 * [
 *      'CONFIG GET', // -Server(服务器)- parameter 返回一个设置参数值
 *      'CONFIG SET', // -Server(服务器)- parameter 设置一个配置参数值
 *      'CONFIG RESETSTAT', // -Server(服务器)- 重置 INFO 命令中的某些统计数据
 * ]
 * -SCRIPT-
 * 1.在 "yii-redis" 中,方法分别为: configGet(),configSet(),configResetstat(),
 * 2.在 "php redis" 中,统一为 config()输入参数的方式
 * [
 *      'SCRIPT EXISTS', // script [script ...] -Script(脚本)- 给定一个或多个脚本的 SHA1 校验和,返回一个包含 0 和 1 的列表,表示校验和所指定的脚本是否已经被保存在缓存当中。
 *      'SCRIPT FLUSH', // -Script(脚本)- 清除所有 Lua 脚本缓存。
 *      'SCRIPT KILL', // -Script(脚本)- 杀死当前正在运行的 Lua 脚本,当且仅当这个脚本没有执行过任何写操作时,这个命令才生效。
 *      'SCRIPT LOAD', // script -Script(脚本)- 将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。
 * ]
 *
 * 二、"yii-redis" 支持,但 "php redis" 不支持的操作:
 * [
 *      'DEBUG OBJECT', // -Server(服务器)- 通过key来获取调试信息,但它不应被客户端所使用。
 *      'DEBUG SEGFAULT', // -Server(服务器)- 执行一个不合法的内存访问从而让 Redis 崩溃,仅在开发时用于 BUG 模拟。
 *      'MONITOR', // -Server(服务器)- 实时打印出 Redis 服务器接收到的命令,调试用。
 *      'SHUTDOWN', // [NOSAVE] [SAVE] -Server(服务器)- 异步保存数据到硬盘并关闭服务器
 *      'SYNC', // -Server(服务器)- 用于复制功能(replication)的内部命令。
 *      'GEOADD', // key longitude latitude member [longitude latitude member ...] -GEO(地理位置)- 添加坐标
 *      'GEODIST', // key member1 member2 [unit] -GEO(地理位置)-  返回两个成员之间的距离
 *      'GEOHASH', // key member [member ...] -GEO(地理位置)- 返回一个或多个位置元素的 Geohash 表示。
 *      'GEOPOS', // key member [member ...] -GEO(地理位置)- 从键里面返回所有给定位置元素的位置(经度和纬度)。
 *      'GEORADIUS', // key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] -GEO(地理位置)- 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
 *      'GEORADIUSBYMEMBER', // key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] -GEO(地理位置)- 这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点。
 * ]
 *
 * 三、"yii-redis" 和 "php redis" 等同的方法:
 * QUIT => close()
 *
 * ----------适配器目前不考虑支持的方法\\END-------------
 *
 * Class BaseRedis
 * @package common\components\redis\connection
 */
abstract class BaseConnection extends Component implements IConnection
{
    public $connection;
    /**
     * @var string 连接REDIS服务器的IP地址,默认为'localhost'连接本地服务器
     */
    public $hostname = 'localhost';
    /**
     * @var integer 连接REDIS服务器的端口,默认是6379.
     */
    public $port = 6379;
    /**
     * @var string 连接REDIS服务器的密码. NULL的时候,不发送AUTH命令
     * See http://redis.io/commands/auth
     */
    public $password;
    /**
     * @var integer 当前连接的REDIS数据库. 默认是0.
     */
    public $database = 0;
    /**
     * @var float 连接REDIS服务器的超时时间. 默认在yii2模式下ini_get('default_socket_timeout'),php redis下使用其默认的超时时间
     */
    public $connectionTimeout;
    /**
     * @var array
     */
    public $redisCommands = [
        'BLPOP', // key [key ...] timeout -list(列表)- 移除并弹出列表的第一个元素,阻塞直到该元素存在或有效
        'BRPOP', // key [key ...] timeout -list(列表)- 移除并弹出列表的最后一个元素,阻塞直到该元素存在或有效
        'BRPOPLPUSH', // source  -list(列表)- 弹出列表的一个元素,入列到另一个列表并返回,阻塞直到该元素存在或有效
        //'CLIENT KILL', // ip:port -Server(服务器)- 关闭地址为 ip:port 的客户端连接。
        //'CLIENT LIST', // -Server(服务器)- 以人可读的格式,返回所有连接到服务器的客户端信息和统计数据。
        //'CLIENT GETNAME', // -Server(服务器)- 返回 CLIENT SETNAME 命令为连接设置的名字。因为新创建的连接默认是没有名字的, 对于没有名字的连接, CLIENT GETNAME 返回空白回复。
        //'CLIENT SETNAME', // -Server(服务器)- 为当前连接分配一个名字。 这个名字会显示在 CLIENT LIST 命令的结果中, 用于识别当前正在与服务器进行连接的客户端。
        //'CONFIG GET', // -Server(服务器)- parameter 返回一个设置参数值
        //'CONFIG SET', // -Server(服务器)- parameter 设置一个配置参数值
        //'CONFIG RESETSTAT', // -Server(服务器)- 重置 INFO 命令中的某些统计数据
        'DBSIZE', // -Server(服务器)- 返回当前数据库的 key 的数量。
        //'DEBUG OBJECT', // -Server(服务器)- 通过key来获取调试信息,但它不应被客户端所使用。
        //'DEBUG SEGFAULT', // -Server(服务器)- 执行一个不合法的内存访问从而让 Redis 崩溃,仅在开发时用于 BUG 模拟。
        'DECR', // -String(字符串)- key 将 key 中储存的数字值减一
        'DECRBY', // -String(字符串)- key 将 key 所储存的值减去减量 decrement 。
        'DEL', // key [key ...] -Key(键)- 删除给定的一个或多个 key ,不存在的 key 会被忽略。
        'DISCARD', // -Transaction(事务)- 取消事务,放弃执行事务块内的所有命令。
        'DUMP', // key -Key(键)- 序列化给定 key ,并返回被序列化的值,使用 RESTORE 命令可以将这个值反序列化为 Redis 键。
        'ECHO', // message -Connection(连接- 打印一个特定的信息 message ,测试时使用。
        'EVAL', // script numkeys key [key ...] arg [arg ...] -Script(脚本)- 从 Redis 2.6.0 版本开始,通过内置的 Lua 解释器,可以使用 EVAL 命令对 Lua 脚本进行求值。
        'EVALSHA', // sha1 numkeys key [key ...] arg [arg ...] -Script(脚本)- 根据给定的 sha1 校验码,对缓存在服务器中的Lua脚本进行求值。
        'EXEC', // -Transaction(事务)- 执行所有事务块内的命令。
        'EXISTS', // -Key(键)- 检查给定 key 是否存在。
        'EXPIRE', // -Key(键)- 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
        'EXPIREAT', // -Key(键)-  类似EXPIRE,都用于为 key 设置生存时间。EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
        'FLUSHALL', // -Server(服务器)-  清空整个 Redis 服务器的数据(删除所有数据库的所有 key )。此命令从不失败。
        'FLUSHDB', // -Server(服务器)-  清空当前数据库中的所有 key。此命令从不失败。
        'GET', // -String(字符串- 返回 key 所关联的字符串值。
        'GETBIT', // -String(字符串)- 对 key 所储存的字符串值,获取指定偏移量上的位(bit)。
        'GETRANGE', // -String(字符串)- 返回 key 中字符串值的子字符串,字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内)。
        'GETSET', // -String(字符串)- 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。
        'HDEL', // key -Hash(哈希表)- field [field ...] 删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
        'HEXISTS', // key -Hash(哈希表)- 查看哈希表 key 中,给定域 field 是否存在。
        'HGET', // key -Hash(哈希表)- 返回哈希表 key 中给定域 field 的值。
        'HGETALL', // key -Hash(哈希表)- 返回哈希表 key 中,所有的域和值。
        'HINCRBY', // key -Hash(哈希表)- 为哈希表 key 中的域 field 的值加上增量 increment 。
        'HINCRBYFLOAT', // -Hash(哈希表)- 为哈希表 key 中的域 field 加上浮点数增量 increment 。
        'HKEYS', // key -Hash(哈希表)- 返回哈希表 key 中的所有域。
        'HLEN', // key -Hash(哈希表)- 返回哈希表 key 中域的数量。
        'HMGET', // key -Hash(哈希表)- field [field ...] 返回哈希表 key 中,一个或多个给定域的值
        'HMSET', // key -Hash(哈希表)- field value [field value ...] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
        'HSET', // key -Hash(哈希表)- 将哈希表 key 中的域 field 的值设为 value 。
        'HSETNX', // key -Hash(哈希表)- 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。
        'HVALS', // key -Hash(哈希表)- 返回哈希表 key 中所有域的值。
        'INCR', // key -String(字符串)- 将 key 中储存的数字值增一。
        'INCRBY', // key increment -String(字符串)- 将 key 所储存的值加上增量 increment 。
        'INCRBYFLOAT', // key increment -String(字符串)- 为 key 中所储存的值加上浮点数增量 increment 。
        'INFO', // [section] -Server(服务器)- 以一种易于解释(parse)且易于阅读的格式,返回关于 Redis 服务器的各种信息和统计数值。
        'KEYS', // pattern -Key(键)- 查找所有符合给定模式 pattern 的 key 。
        'LASTSAVE', // -Server(服务器)- 返回最近一次 Redis 成功将数据保存到磁盘上的时间,以 UNIX 时间戳格式表示。
        'LINDEX', // key index -List(列表)- 返回列表 key 中,下标为 index 的元素。
        'LINSERT', // key BEFORE|AFTER pivot value -List(列表)- 将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。
        'LLEN', // key -List(列表)-  返回列表 key 的长度。
        'LPOP', // key -List(列表)- 移除并返回列表 key 的头元素。
        'LPUSH', // key value [value ...] -List(列表)- 将一个或多个值 value 插入到列表 key 的表头
        'LPUSHX', // key value -List(列表)- 将值 value 插入到列表 key 的表头,当且仅当 key 存在并且是一个列表。
        'LRANGE', // key start stop -List(列表)- 返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。
        'LREM', // key count value -List(列表)- 根据参数 count 的值,移除列表中与参数 value 相等的元素。
        'LSET', // key index value -List(列表)- 将列表 key 下标为 index 的元素的值设置为 value 。
        'LTRIM', // key start stop -List(列表)- 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
        'MGET', // key [key ...] -String(字符串)- 返回所有(一个或多个)给定 key 的值。
        'MIGRATE', // host port key destination-db timeout -Key(键)- 将 key 原子性地从当前实例传送到目标实例的指定数据库上,一旦传送成功, key 保证会出现在目标实例上,而当前实例上的 key 会被删除。
        'MONITOR', // -Server(服务器)- 实时打印出 Redis 服务器接收到的命令,调试用。
        'MOVE', // key db -Key(键)- 将当前数据库的 key 移动到给定的数据库 db 当中。
        'MSET', // key value [key value ...] -String(字符串)- 同时设置一个或多个 key-value 对。
        'MSETNX', // key value [key value ...] -String(字符串)- 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在。
        'MULTI', // -Transaction(事务)- 标记一个事务块的开始。
        'OBJECT', // subcommand [arguments [arguments ...]] -Key(键)- OBJECT 命令允许从内部察看给定 key 的 Redis 对象。
        'PERSIST', // key 移除给定 key 的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
        'PEXPIRE', // key milliseconds -Key(键)- 这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。
        'PEXPIREAT', // key milliseconds-timestamp -Key(键)- 这个命令和 EXPIREAT 命令类似,但它以毫秒为单位设置 key 的过期 unix 时间戳,而不是像 EXPIREAT 那样,以秒为单位。
        'PING', // -Connection(连接)- 使用客户端向 Redis 服务器发送一个 PING ,如果服务器运作正常的话,会返回一个 PONG 。
        'PSETEX', // key milliseconds value -String(字符串)- 这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。
        'PSUBSCRIBE', // pattern [pattern ...] -Pub/Sub(发布/订阅)- 订阅一个或多个符合给定模式的频道。
        'PTTL', // key -Key(键)- 这个命令类似于 TTL 命令,但它以毫秒为单位返回 key 的剩余生存时间,而不是像 TTL 命令那样,以秒为单位。
        'PUBLISH', // channel message -Pub/Sub(发布/订阅)- 将信息 message 发送到指定的频道 channel 。
        'PUNSUBSCRIBE', // [pattern [pattern ...]] -Pub/Sub(发布/订阅)- 指示客户端退订所有给定模式。
        //'QUIT', // -Connection(连接)- 请求服务器关闭与当前客户端的连接。
        'RANDOMKEY', // -Key(键)- 从当前数据库中随机返回(不删除)一个 key 。
        'RENAME', // key newkey -Key(键)- 将 key 改名为 newkey 。
        'RENAMENX', // key newkey -Key(键)- 当且仅当 newkey 不存在时,将 key 改名为 newkey 。
        'RESTORE', // key ttl serialized-value -Key(键)- 反序列化给定的序列化值,并将它和给定的 key 关联。
        'RPOP', // key -List(列表)- 移除并返回列表 key 的尾元素。
        'RPOPLPUSH', // source destination -List(列表)- 从列表中移除最后一个元素,并推到一个新的队列。
        'RPUSH', // key value [value ...] -List(列表)- 将一个或多个值 value 插入到列表 key 的表尾(最右边)。
        'RPUSHX', // key value -List(列表)- 将值 value 插入到列表 key 的表尾,当且仅当 key 存在并且是一个列表。
        'SADD', // key member [member ...] -Set(集合)- 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
        'SAVE', // -Server(服务器)- SAVE 命令执行一个同步保存操作,将当前 Redis 实例的所有数据快照(snapshot)以 RDB 文件的形式保存到硬盘。
        'SCARD', // key -Set(集合)-返回集合 key 的基数(集合中元素的数量)。
        'SCRIPT EXISTS', // script [script ...] -Script(脚本)- 给定一个或多个脚本的 SHA1 校验和,返回一个包含 0 和 1 的列表,表示校验和所指定的脚本是否已经被保存在缓存当中。
        //'SCRIPT FLUSH', // -Script(脚本)- 清除所有 Lua 脚本缓存。
        //'SCRIPT KILL', // -Script(脚本)- 杀死当前正在运行的 Lua 脚本,当且仅当这个脚本没有执行过任何写操作时,这个命令才生效。
        //'SCRIPT LOAD', // script -Script(脚本)- 将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。
        'SDIFF', // key [key ...] -Set(集合)- 返回一个集合的全部成员,该集合是所有给定集合之间的差集。
        'SDIFFSTORE', // destination key [key ...] -Set(集合)- 这个命令的作用和 SDIFF 类似,但它将结果保存到 destination 集合,而不是简单地返回结果集。
        'SELECT', // index -Connection(连接)- 切换到指定的数据库,数据库索引号 index 用数字值指定,以 0 作为起始索引值。
        'SET', // key value -String(字符串)- 将字符串值 value 关联到 key 。
        'SETBIT', // key offset value -String(字符串)- 对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
        'SETEX', // key seconds value -String(字符串)- 将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。
        'SETNX', // key value -String(字符串)- 将 key 的值设为 value ,当且仅当 key 不存在。
        'SETRANGE', // key offset value -String(字符串)- 用 value 参数覆写(overwrite)给定 key 所储存的字符串值,从偏移量 offset 开始。
        'SHUTDOWN', // [NOSAVE] [SAVE] -Server(服务器)- 异步保存数据到硬盘并关闭服务器
        'SINTER', // key [key ...] -Set(集合)- 返回一个集合的全部成员,该集合是所有给定集合的交集。
        'SINTERSTORE', // destination key [key ...] -Set(集合)- 这个命令类似于 SINTER 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。
        'SISMEMBER', // key member -Set(集合)- 判断 member 元素是否集合 key 的成员。
        'SLAVEOF', // host port SLAVEOF 命令用于在 Redis 运行时动态地修改复制(replication)功能的行为。
        'SLOWLOG', // subcommand [argument] -Server(服务器)- Redis 用来记录查询执行时间的日志系统。
        'SMEMBERS', // key -Set(集合)- 返回集合 key 中的所有成员。
        'SMOVE', // source destination member -Set(集合)- 将 member 元素从 source 集合移动到 destination 集合。
        'SORT', // key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]] [ASC|DESC] [ALPHA] [STORE destination] -Key(键)- 返回或保存给定列表、集合、有序集合 key 中经过排序的元素。
        'SPOP', // key -Set(集合)- 移除并返回集合中的一个随机元素。
        'SRANDMEMBER', // key [count] -Set(集合)- 如果命令执行时,只提供了 key 参数,那么返回集合中的一个随机元素。
        'SREM', // key member [member ...] -Set(集合)- 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。
        'STRLEN', // key -String(字符串)- 返回 key 所储存的字符串值的长度。
        'SUBSCRIBE', // channel [channel ...] -Pub/Sub(发布/订阅)- 订阅给定的一个或多个频道的信息。
        'SUNION', // key [key ...] -Set(集合)- 返回一个集合的全部成员,该集合是所有给定集合的并集
        'SUNIONSTORE', // destination key [key ...] -Set(集合)- 这个命令类似于 SUNION 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。
        'SYNC', // -Server(服务器)- 用于复制功能(replication)的内部命令。
        'TIME', // -Server(服务器)- 返回当前服务器时间。
        'TTL', // key -Key(键)- 以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
        'TYPE', // key -Key(键)- 返回 key 所储存的值的类型。
        'UNSUBSCRIBE', // [channel [channel ...]] -Pub/Sub(发布/订阅)- 指示客户端退订给定的频道。
        'UNWATCH', // -Transaction(事务)- 取消 WATCH 命令对所有 key 的监视。
        'WATCH', // key [key ...] -Transaction(事务)-  监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。
        'ZADD', // key score member [score member ...] -SortedSet(有序集合)- 将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
        'ZCARD', // key -SortedSet(有序集合)- 返回有序集 key 的基数。
        'ZCOUNT', // key min max -SortedSet(有序集合)- 返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。
        'ZINCRBY', // key increment member -SortedSet(有序集合)- 为有序集 key 的成员 member 的 score 值加上增量 increment 。
        'ZINTERSTORE', // destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] -SortedSet(有序集合)- 计算给定的一个或多个有序集的交集,其中给定 key 的数量必须以 numkeys 参数指定,并将该交集(结果集)储存到 destination 。
        'ZRANGE', // key start stop [WITHSCORES] -SortedSet(有序集合)- 返回有序集 key 中,指定区间内的成员。
        'ZRANGEBYSCORE', // key min max [WITHSCORES] [LIMIT offset count] -SortedSet(有序集合)- 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
        'ZRANK', // key member -SortedSet(有序集合)- 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。
        'ZREM', // key member [member ...] -SortedSet(有序集合)- 移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。
        'ZREMRANGEBYRANK', // key start stop -SortedSet(有序集合)- 移除有序集 key 中,指定排名(rank)区间内的所有成员。
        'ZREMRANGEBYSCORE', // key min max -SortedSet(有序集合)- 移除有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。
        'ZREVRANGE', // key start stop [WITHSCORES] -SortedSet(有序集合)- 返回有序集 key 中,指定区间内的成员。
        'ZREVRANGEBYSCORE', // key max min [WITHSCORES] [LIMIT offset count] -SortedSet(有序集合)- 返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。
        'ZREVRANK', // key member -SortedSet(有序集合)- 返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。
        'ZSCORE', // key member -SortedSet(有序集合)- 返回有序集 key 中,成员 member 的 score 值。
        'ZUNIONSTORE', // destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX] -SortedSet(有序集合)- 计算给定的一个或多个有序集的并集,其中给定 key 的数量必须以 numkeys 参数指定,并将该并集(结果集)储存到 destination 。
        //'GEOADD', // key longitude latitude member [longitude latitude member ...] -GEO(地理位置)- 添加坐标
        //'GEODIST', // key member1 member2 [unit] -GEO(地理位置)-  返回两个成员之间的距离
        //'GEOHASH', // key member [member ...] -GEO(地理位置)- 返回一个或多个位置元素的 Geohash 表示。
        //'GEOPOS', // key member [member ...] -GEO(地理位置)- 从键里面返回所有给定位置元素的位置(经度和纬度)。
        //'GEORADIUS', // key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] -GEO(地理位置)- 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
        //'GEORADIUSBYMEMBER', // key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] -GEO(地理位置)- 这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点。
    ];

    /**
     * 被序列化的时候关闭当前连接
     * @return array
     */
    public function __sleep()
    {
        $this->close();
        return array_keys(get_object_vars($this));
    }

    /**
     * 当前REDIS链接是否有效
     * @return boolean 当前REDIS链接是否有效
     */
    public abstract function getIsActive();

    /**
     * 打开一个REDIS连接
     * 如果已经打开过了,直接返回,什么都不做。
     * @throws Exception 连接失败
     */
    public abstract function open();

    /**
     * 关闭当前REDIS连接
     * 当连接已被关闭时,什么有何不做。
     */
    public abstract function close();

    /**
     * 当前驱动器名称,yii redis 和 php redis 两种,一个是yii2的redis扩展,一个是PHP的C扩展
     * @return string 当前驱动器名称
     */
    public abstract function getDriverName();

    /**
     * 由子类调用具体的接口去实现
     * @param $name
     * @param $params
     * @return mixed
     */
    protected abstract function call($name, $params);

    /**
     * 允许通过魔法方法访问所有已支持的REDIS命令
     *
     * ```php
     * $redis->hmset(['test_collection', 'key1', 'val1', 'key2', 'val2'])
     *
     * ```
     * @param string $name 将被调用的方法名称
     * @param array $params 将被调用的方法参数数组
     * @return mixed
     */
    public function __call($name, $params)
    {
        $redisCommand = strtoupper($name);
        if (in_array($redisCommand, $this->redisCommands)) {
            return $this->call($name, $params);
        } else {
            return parent::__call($name, $params);
        }
    }

    /**
     * 创建一个新的事务上下文,
     * 1.当定义回调函数$callable时,直接调用```php $transaction->execute()```执行并返回结果。
     * 2.没有定义回调函数$callable时,返回```php return $transaction ```
     * @param array|null $options 选项设置
     * @param null $callable 回调函数
     * @return array|MultiExecTransaction
     * @throws \Exception
     * @throws AbortedMultiExecException
     */
    public function transaction(array $options = [], $callable = null)
    {
        $transaction = new MultiExecTransaction($this, $options);

        if (isset($callable)) {
            return $transaction->execute($callable);
        }

        return $transaction;
    }
}