├── Demo.php ├── LICENSE ├── README.md ├── composer.json ├── src ├── CoRedis.php ├── RedisPool.php └── map │ └── CoRedisMap.php └── version.md /Demo.php: -------------------------------------------------------------------------------- 1 | server = new Swoole\Http\Server("0.0.0.0", 9501); 22 | $this->server->set(array( 23 | 'worker_num' => 4, 24 | 'max_request' => 50000, 25 | 'reload_async' => true, 26 | 'max_wait_time' => 30, 27 | )); 28 | $this->server->on('Start', function ($server) { 29 | }); 30 | $this->server->on('ManagerStart', function ($server) { 31 | }); 32 | $this->server->on('WorkerStart', array($this, 'onWorkerStart')); 33 | $this->server->on('WorkerStop', function ($server, $worker_id) { 34 | }); 35 | $this->server->on('open', function ($server, $request) { 36 | }); 37 | $this->server->on('Request', array($this, 'onRequest')); 38 | $this->server->start(); 39 | } 40 | 41 | public function onWorkerStart($server, $worker_id) 42 | { 43 | $config = [ 44 | 'host' => '127.0.0.1', 45 | 'port' => 6379, 46 | 'auth' => 'sethink', 47 | 'poolMin' => 5, 48 | 'clearTime' => 60000, 49 | 'clearAll' => 300000, 50 | 'setDefer' => true, 51 | 'timeout' => 5 52 | ]; 53 | $this->RedisPool = new RedisPool($config); 54 | unset($config); 55 | 56 | $this->RedisPool->clearTimer($this->server); 57 | } 58 | 59 | public function onRequest($request, $response) 60 | { 61 | // $rs1 = CoRedis::init($this->RedisPool) 62 | // ->setDefer(false) 63 | // ->set('sethink', 'sethink'); 64 | // var_dump($rs1); 65 | $rs2 = CoRedis::init($this->RedisPool)->get('sethink'); 66 | // var_dump($rs2); 67 | 68 | // $redis = CoRedis::init($this->RedisPool)->instance(); 69 | // CoRedis::init($this->RedisPool)->put($redis); 70 | 71 | // go(function (){ 72 | // $redis = CoRedis::init($this->RedisPool)->instance(); 73 | // $rs = $redis->get('string'); 74 | // var_dump($rs); 75 | // CoRedis::init($this->RedisPool)->put($redis); 76 | // }); 77 | echo PHP_EOL; 78 | } 79 | } 80 | 81 | new Demo(); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # swoole-redis 2 | ``` 3 | 基于swoole的redis协程连接池,简单封装。 4 | 实现多个协程间共用同一个协程客户端。 5 | 6 | tip: 7 | 实现redis函数的基本提示(部分函数未实现) 8 | ``` 9 | 10 | # 版本 11 | ## v0.0.1 12 | ``` 13 | 1、初完成 14 | 15 | ``` 16 | ## v0.0.2 17 | ``` 18 | 1、添加setDefer -> 设置是否返回结果(默认为true。部分操作,如果不需要返回返回结果,则可以设置为false) 19 | 2、使用go处理协程 20 | 21 | ``` 22 | 23 | ## v0.0.3 24 | ``` 25 | 1、添加setOptions配置(swoole官方timeout设置"超时时间, 默认为全局的协程socket_timeout(-1, 永不超时)"。在使用brPop函数时,发现好似并未生效,timeout的设置必须大于brPop超时,否则会出现"Resource temporarily unavailable") 26 | 2、添加断线重连功能 27 | 3、添加instance()函数,如果有特殊需求扩展无法实现,又想共用连接池时,譬如事务处理,此时可以通过instance获取一个连接 28 | 4、添加put()函数,配合instance使用,使用完连接后,将连接put回连接池里 29 | 5、添加异常处理 30 | ``` 31 | 32 | # 引入 33 | ``` 34 | >composer require sethink/swoole-redis 35 | ``` 36 | 37 | 38 | 39 | # 入门例子 40 | ```php 41 | server = new Swoole\Http\Server("0.0.0.0", 9501); 59 | $this->server->set(array( 60 | 'worker_num' => 4, 61 | 'max_request' => 50000, 62 | 'reload_async' => true, 63 | 'max_wait_time' => 30 64 | )); 65 | $this->server->on('Start', function ($server) {}); 66 | $this->server->on('ManagerStart', function ($server) {}); 67 | $this->server->on('WorkerStart', array($this, 'onWorkerStart')); 68 | $this->server->on('WorkerStop', function ($server, $worker_id) {}); 69 | $this->server->on('open', function ($server, $request) {}); 70 | $this->server->on('Request', array($this, 'onRequest')); 71 | $this->server->start(); 72 | } 73 | 74 | public function onWorkerStart($server, $worker_id) 75 | { 76 | $config = [ 77 | 'host' => '127.0.0.1', 78 | 'port' => 6379, 79 | 'auth' => 'sethink', 80 | 'poolMin' => 5, //空闲时,保存的最大链接,默认为5 81 | 'poolMax' => 1000, //地址池最大连接数,默认1000 82 | 'clearTime' => 60000, //清除空闲链接的定时器,默认60s 83 | 'clearAll' => 300000, //空闲多久清空所有连接,默认300s 84 | 'setDefer' => true, //设置是否返回结果 85 | //options设置 86 | 'connect_timeout' => 1, //连接超时时间,默认为1s 87 | 'timeout' => 1, //超时时间,默认为1s 88 | 'serialize' => false, //自动序列化,默认false 89 | 'reconnect' => 1 //自动连接尝试次数,默认为1次 90 | ]; 91 | $this->RedisPool = new RedisPool($config); 92 | unset($config); 93 | 94 | //定时器,清除空闲连接 95 | $this->RedisPool->clearTimer($this->server); 96 | } 97 | 98 | public function onRequest($request, $response) 99 | { 100 | $rs1 = CoRedis::init($this->RedisPool)->set('sethink', 'sethink'); 101 | var_dump($rs1); 102 | $rs2 = CoRedis::init($this->RedisPool)->get('sethink'); 103 | var_dump($rs2); 104 | } 105 | } 106 | 107 | new Demo(); 108 | 109 | ``` 110 | 111 | # 详解 112 | ## instance() 113 | ``` 114 | 如果有特殊需求扩展无法实现,又想共用连接池时,譬如事务处理,此时可以通过instance获取一个连接 115 | ``` 116 | 117 | ```php 118 | RedisPool)->instance(); 121 | $rs = $redis->get('sethink'); 122 | var_dump($rs); 123 | }); 124 | ``` 125 | 126 | ## put($redis) 127 | ``` 128 | 配合instance使用,使用完连接后,将连接put回连接池里。 129 | $redis是连接池的连接 130 | ``` 131 | 132 | ```php 133 | RedisPool)->instance(); 136 | $rs = $redis->get('sethink'); 137 | var_dump($rs); 138 | CoRedis::init($redis); 139 | }); 140 | ``` 141 | 142 | 143 | ## setDefer($bool) 144 | ``` 145 | 部分操作,如果不需要返回结果,则可以设置为false。 146 | 147 | 相对于$bool为true,执行后,由于主进程和协程间不需要再通信,可以立即往下执行程序 148 | ``` 149 | 150 | ```php 151 | RedisPool) 154 | ->setDefer(false) 155 | ->set('sethink', 'sethink'); 156 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sethink/swoole-redis", 3 | "description": "sethink", 4 | "license": "Apache-2.0", 5 | "authors": [ 6 | { 7 | "name": "sethink", 8 | "email": "358066237@qq.com" 9 | } 10 | ], 11 | "require": { 12 | "php":">=7.0.0", 13 | "ext-swoole":">=4.2.7" 14 | }, 15 | "autoload": { 16 | "psr-4": { 17 | "sethink\\swooleRedis\\":"src" 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/CoRedis.php: -------------------------------------------------------------------------------- 1 | '127.0.0.1', 24 | //端口 25 | 'port' => 6379, 26 | //密码 27 | 'auth' => '', 28 | //数据库 29 | 'db' => 0, 30 | //空闲时,保存的最大链接,默认为5 31 | 'poolMin' => 5, 32 | //地址池最大连接数,默认1000 33 | 'poolMax' => 1000, 34 | //清除空闲链接的定时器,默认60s 35 | 'clearTime' => 60000, 36 | //空闲多久清空所有连接,默认300s 37 | 'clearAll' => 300, 38 | //设置是否返回结果 39 | 'setDefer' => true, 40 | 41 | //options配置 42 | 'connect_timeout' => 1, //连接超时时间,默认为1s 43 | 'timeout' => 1, //超时时间,默认为1s 44 | 'serialize' => false, //自动序列化,默认false 45 | 'reconnect' => 1 //自动连接尝试次数,默认为1次 46 | ]; 47 | 48 | public function __construct($config) 49 | { 50 | if (isset($config['clearAll'])) { 51 | if ($config['clearAll'] < $config['clearTime']) { 52 | $config['clearAll'] = (int)($config['clearTime'] / 1000); 53 | } else { 54 | $config['clearAll'] = (int)($config['clearAll'] / 1000); 55 | } 56 | } 57 | 58 | $this->config = array_merge($this->config, $config); 59 | $this->pool = new Swoole\Coroutine\Channel($this->config['poolMax']); 60 | } 61 | 62 | /** 63 | * @入池 64 | * 65 | * @param $redis 66 | */ 67 | public function put($redis) 68 | { 69 | //未超出池最大值时 70 | if ($this->pool->length() < $this->config['poolMax']) { 71 | $this->pool->push($redis); 72 | } 73 | $this->pushTime = time(); 74 | } 75 | 76 | /** 77 | * @出池 78 | */ 79 | public function get() 80 | { 81 | $re_i = -1; 82 | 83 | back: 84 | $re_i++; 85 | 86 | if (!$this->available) { 87 | $this->dumpException('Redis连接池正在销毁'); 88 | } 89 | 90 | //有空闲连接且连接池处于可用状态 91 | if ($this->pool->length() > 0) { 92 | $redis = $this->pool->pop(); 93 | } else { 94 | //无空闲连接,创建新连接 95 | $redis = new Swoole\Coroutine\Redis([ 96 | 'connect_timeout' => $this->config['connect_timeout'], 97 | 'timeout' => $this->config['timeout'], 98 | 'serialize' => $this->config['serialize'], 99 | 'reconnect' => $this->config['reconnect'] 100 | ]); 101 | 102 | $redis->connect($this->config['host'], $this->config['port']); 103 | 104 | if (!empty($this->config['auth'])) { 105 | $redis->auth($this->config['auth']); 106 | } 107 | 108 | $redis->select($this->config['db']); 109 | 110 | $this->addPoolTime = time(); 111 | } 112 | 113 | if ($redis->connected === true && $redis->errCode === 0) { 114 | return $redis; 115 | } else { 116 | if ($re_i <= $this->config['poolMin']) { 117 | $this->dumpError("redis-重连次数{$re_i},[errCode:{$redis->errCode},errMsg:{$redis->errMsg}]"); 118 | 119 | $redis->close(); 120 | unset($redis); 121 | goto back; 122 | } 123 | 124 | $this->dumpException('Redis重连失败'); 125 | } 126 | } 127 | 128 | /** 129 | * @定时器 130 | * 131 | * @param $server 132 | */ 133 | public function clearTimer($server) 134 | { 135 | $server->tick($this->config['clearTime'], function () use ($server) { 136 | if ($this->pool->length() > $this->config['poolMin'] && time() - 5 > $this->addPoolTime) { 137 | $this->pool->pop(); 138 | } 139 | if ($this->pool->length() > 0 && time() - $this->config['clearAll'] > $this->pushTime) { 140 | while (!$this->pool->isEmpty()) { 141 | $this->pool->pop(); 142 | } 143 | } 144 | }); 145 | } 146 | 147 | 148 | /** 149 | * @打印错误信息 150 | * 151 | * @param $msg 152 | */ 153 | public function dumpError($msg) 154 | { 155 | var_dump(date('Y-m-d H:i:s', time()) . ":{$msg}"); 156 | } 157 | 158 | 159 | /** 160 | * @抛出异常 161 | * 162 | * @param $msg 163 | */ 164 | public function dumpException($msg) 165 | { 166 | throw new \RuntimeException(date('Y-m-d H:i:s', time()) . ":{$msg}"); 167 | } 168 | 169 | public function destruct() 170 | { 171 | // 连接池销毁, 置不可用状态, 防止新的客户端进入常驻连接池, 导致服务器无法平滑退出 172 | $this->available = false; 173 | while (!$this->pool->isEmpty()) { 174 | $this->pool->pop(); 175 | } 176 | } 177 | } -------------------------------------------------------------------------------- /src/map/CoRedisMap.php: -------------------------------------------------------------------------------- 1 | true 13 | ]; 14 | 15 | protected $sethink_array = [ 16 | 'init', 17 | 'instance', 18 | 'put', 19 | 'setDefer' 20 | ]; 21 | protected $base_array = [ 22 | 'ping', 23 | 'echo', 24 | 'randomKey', 25 | 'select', 26 | 'move', 27 | 'rename', 28 | 'renameNx', 29 | 'expire', 30 | 'pexpire', 31 | 'expireAt', 32 | 'pexpireAt', 33 | 'keys', 34 | 'dbSize', 35 | 'object', 36 | 'save', 37 | 'bgsave', 38 | 'lastSave', 39 | 'type', 40 | 'flushDB', 41 | 'flushAll', 42 | 'sort', 43 | 'info', 44 | 'resetStat', 45 | 'ttl', 46 | 'pttl', 47 | 'persist', 48 | 'eval', 49 | 'evalSha', 50 | 'script', 51 | 'getLastError', 52 | '_prefix', 53 | '_unseriablize', 54 | 'dump', 55 | 'restore', 56 | 'time' 57 | ]; 58 | protected $string_array = [ 59 | 'get', 60 | 'set', 61 | 'setex', 62 | 'psetex', 63 | 'setnx', 64 | 'del', 65 | 'delete', 66 | 'getSet', 67 | 'exists', 68 | 'incr', 69 | 'incrBy', 70 | 'incrByFloat', 71 | 'decr', 72 | 'decrBy', 73 | 'mget', 74 | 'append', 75 | 'getRange', 76 | 'setRange', 77 | 'strlen', 78 | 'getBit', 79 | 'setBit', 80 | 'mset' 81 | ]; 82 | protected $list_array = [ 83 | 'lPush', 84 | 'rPush', 85 | 'lPushx', 86 | 'rPushx', 87 | 'lPop', 88 | 'rPop', 89 | 'blpop', 90 | 'brpop', 91 | 'lSize', 92 | 'lGet', 93 | 'lSet', 94 | 'IRange', 95 | 'lTrim', 96 | 'lRem', 97 | 'rpoplpush', 98 | 'brpoplush' 99 | ]; 100 | protected $set_array = [ 101 | 'sAdd', 102 | 'sRem', 103 | 'sMove', 104 | 'sInMember', 105 | 'sCard', 106 | 'sPop', 107 | 'sRandMember', 108 | 'sInter', 109 | 'sInterStore', 110 | 'sUnion', 111 | 'sUnionStore', 112 | 'sDiff', 113 | 'sDiffStore', 114 | 'sMembers' 115 | ]; 116 | protected $zset_array = [ 117 | 'zAdd', 118 | 'zRange', 119 | 'zDelete', 120 | 'zRevRange', 121 | 'zRangeByScore', 122 | 'zCount', 123 | 'zRemRangeByScore', 124 | 'zRemRangeByRank', 125 | 'zSize', 126 | 'zScore', 127 | 'zRank', 128 | 'zRevRank', 129 | 'zIncrBy' 130 | ]; 131 | protected $hash_array = [ 132 | 'hSet', 133 | 'hSetNx', 134 | 'hGet', 135 | 'hLen', 136 | 'hDel', 137 | 'hKeys', 138 | 'hVals', 139 | 'hGetAll', 140 | 'hExists', 141 | 'hIncrBy', 142 | 'hIncrByFloat', 143 | 'hMset', 144 | 'hMGet' 145 | ]; 146 | protected $key_array = []; 147 | 148 | public function __construct() 149 | { 150 | $this->key_array = array_merge($this->sethink_array,$this->base_array,$this->string_array,$this->list_array,$this->set_array,$this->zset_array,$this->hash_array); 151 | } 152 | 153 | 154 | /** 155 | * @文件信息 156 | * 157 | * @return string 158 | */ 159 | protected function class_info (){ 160 | return json_encode(debug_backtrace()); 161 | } 162 | 163 | 164 | /** 165 | * @错误信息格式 166 | * 167 | * @param $class_info 168 | */ 169 | protected function dumpError($class_info){ 170 | echo PHP_EOL.PHP_EOL.PHP_EOL; 171 | echo "=================================================================".PHP_EOL; 172 | echo "时间:".date('Y-m-d H:m:i',time()).PHP_EOL.PHP_EOL; 173 | echo "报错信息:(格式为json,请格式化后分析)".PHP_EOL; 174 | echo $class_info.PHP_EOL; 175 | } 176 | 177 | 178 | public function init($RedisPool) 179 | { 180 | $this->RedisPool = $RedisPool; 181 | $this->options['setDefer'] = $RedisPool->config['setDefer']; 182 | return $this; 183 | } 184 | 185 | public function instance() 186 | { 187 | return $this->RedisPool->get(); 188 | } 189 | 190 | public function put($redis) 191 | { 192 | if ($redis instanceof \Swoole\Coroutine\Redis) { 193 | $this->RedisPool->put($redis); 194 | } else { 195 | $class_info = $this->class_info(); 196 | $this->dumpError($class_info); 197 | throw new \RuntimeException('传入的$redis不属于该连接池'); 198 | } 199 | } 200 | 201 | public function setDefer($bool = true) 202 | { 203 | $this->options['setDefer'] = $bool; 204 | return $this; 205 | } 206 | 207 | protected function query($method, $args) 208 | { 209 | $chan = new \chan(1); 210 | 211 | $class_info = $this->class_info(); 212 | 213 | go(function () use ($chan, $method, $args,$class_info) { 214 | $redis = $this->RedisPool->get(); 215 | 216 | $rs = call_user_func_array([$redis, $method], $args); 217 | 218 | $this->put($redis); 219 | 220 | if ($this->options['setDefer']) { 221 | $chan->push($rs); 222 | } 223 | }); 224 | 225 | if ($this->options['setDefer']) { 226 | return $chan->pop(); 227 | } 228 | return; 229 | } 230 | 231 | public function __call($method, $args) 232 | { 233 | if ($this->RedisPool) { 234 | if(in_array($method,$this->key_array)){ 235 | return $this->query($method, $args); 236 | }else{ 237 | $class_info = $this->class_info(); 238 | $this->dumpError($class_info); 239 | echo PHP_EOL."错误信息:{{{$method}}}方法不存在".PHP_EOL; 240 | } 241 | } else { 242 | $class_info = $this->class_info(); 243 | $this->dumpError($class_info); 244 | echo PHP_EOL."错误信息:请先执行init()函数".PHP_EOL; 245 | } 246 | } 247 | } -------------------------------------------------------------------------------- /version.md: -------------------------------------------------------------------------------- 1 | ``` 2 | v0.0.3 3 | 1、添加setOptions配置(swoole官方timeout设置"超时时间, 默认为全局的协程socket_timeout(-1, 永不超时)"。在使用brPop函数时,发现好似并未生效,timeout的设置必须大于brPop超时,否则会出现"Resource temporarily unavailable") 4 | 2、添加断线重连功能 5 | 3、添加instance()函数,如果有特殊需求扩展无法实现,又想共用连接池时,譬如事务处理,此时可以通过instance获取一个连接 6 | 4、添加put()函数,配合instance使用,使用完连接后,将连接put回连接池里 7 | 5、添加异常处理 8 | ``` --------------------------------------------------------------------------------