cache.redis.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <?php
  2. /**
  3. * redis 操作
  4. */
  5. defined('InShopNC') or exit('Access Invalid!');
  6. class Cacheredis extends Cache
  7. {
  8. private $config;
  9. private $type;
  10. private $prefix;
  11. private $master;
  12. private $slave;
  13. public function __construct()
  14. {
  15. $this->config = C('redis');
  16. if (empty($this->config['slave'])) $this->config['slave'] = $this->config['master'];
  17. $this->prefix = $this->config['prefix'] ? $this->config['prefix'] : substr(md5($_SERVER['HTTP_HOST']), 0, 6).'_';
  18. if ( !extension_loaded('redis') ) {
  19. throw_exception('redis failed to load');
  20. }
  21. $this->master = null;
  22. $this->slave = null;
  23. }
  24. public function __destruct()
  25. {
  26. if(defined('USE_COROUTINE') && USE_COROUTINE && defined('COROUTINE_HOOK_TCP') && COROUTINE_HOOK_TCP)
  27. {
  28. if(!CoRedisPool::instance()->stoped())
  29. {
  30. $other = co_create_instance('Cache','connect',['cacheredis']);
  31. $other->attach($this->master,$this->slave);
  32. $this->master = null;
  33. $this->slave = null;
  34. CoRedisPool::instance()->put($other);
  35. }
  36. }
  37. }
  38. private function attach($master,$slave)
  39. {
  40. $this->master = $master;
  41. $this->slave = $slave;
  42. }
  43. private function init_master()
  44. {
  45. if(defined('USE_COROUTINE') && USE_COROUTINE && defined('COROUTINE_HOOK_TCP') && COROUTINE_HOOK_TCP)
  46. {
  47. if (!is_null($this->master))
  48. {
  49. if($this->master->isConnected()) {
  50. $this->handler = $this->master;
  51. $this->enable = true;
  52. return;
  53. } else {
  54. $this->master->close();
  55. Log::record("CacheRedis init_slave disconnect.",Log::DEBUG);
  56. }
  57. }
  58. if (is_mobile()) {
  59. $func = 'connect';
  60. } else {
  61. $func = $this->config['pconnect'] ? 'pconnect' : 'connect';
  62. }
  63. $this->master = new Redis();
  64. $this->enable = $this->master->$func($this->config['master']['host'], $this->config['master']['port']);
  65. }
  66. else
  67. {
  68. static $_cache;
  69. if (isset($_cache))
  70. {
  71. if($_cache->isConnected()) {
  72. $this->master = $_cache;
  73. $this->handler = $this->master;
  74. $this->enable = true;
  75. return;
  76. } else {
  77. $_cache->close();
  78. Log::record("CacheRedis init_slave disconnect.",Log::DEBUG);
  79. }
  80. }
  81. if (is_mobile()) {
  82. $func = 'connect';
  83. } else {
  84. $func = $this->config['pconnect'] ? 'pconnect' : 'connect';
  85. }
  86. $this->master = new Redis();
  87. $this->enable = $this->master->$func($this->config['master']['host'], $this->config['master']['port']);
  88. $_cache = $this->master;
  89. }
  90. $this->handler = $this->master;
  91. }
  92. private function init_slave()
  93. {
  94. if(defined('USE_COROUTINE') && USE_COROUTINE && defined('COROUTINE_HOOK_TCP') && COROUTINE_HOOK_TCP)
  95. {
  96. if (!is_null($this->slave))
  97. {
  98. if($this->slave->isConnected()) {
  99. $this->handler = $this->slave;
  100. $this->enable = true;
  101. return;
  102. } else {
  103. $this->slave->close();
  104. Log::record("CacheRedis init_slave disconnect.",Log::DEBUG);
  105. }
  106. }
  107. if (is_mobile()) {
  108. $func = 'connect';
  109. } else {
  110. $func = $this->config['pconnect'] ? 'pconnect' : 'connect';
  111. }
  112. $this->slave = new Redis();
  113. $this->enable = $this->slave->$func($this->config['slave']['host'], $this->config['slave']['port']);
  114. }
  115. else
  116. {
  117. static $_cache;
  118. if (isset($_cache))
  119. {
  120. if($_cache->isConnected()) {
  121. $this->slave = $_cache;
  122. $this->enable = true;
  123. return;
  124. } else {
  125. $_cache->close();
  126. Log::record("CacheRedis init_slave disconnect.",Log::DEBUG);
  127. }
  128. }
  129. if (is_mobile()) {
  130. $func = 'connect';
  131. } else {
  132. $func = $this->config['pconnect'] ? 'pconnect' : 'connect';
  133. }
  134. $this->slave = new Redis();
  135. $this->enable = $this->slave->$func($this->config['slave']['host'], $this->config['slave']['port']);
  136. $_cache = $this->slave;
  137. }
  138. $this->handler = $this->slave;
  139. }
  140. public function get($key, $prefix = '')
  141. {
  142. $this->init_slave();
  143. if (!$this->enable) return false;
  144. $this->type = $prefix;
  145. $value = $this->handler->get($this->_key($key));
  146. return unserialize($value);
  147. }
  148. public function set($key, $value, $prefix = '', $expire = null)
  149. {
  150. $this->init_master();
  151. if (!$this->enable) return false;
  152. $this->type = $prefix;
  153. $value = serialize($value);
  154. if(is_int($expire)) {
  155. $result = $this->handler->setex($this->_key($key), $expire, $value);
  156. }else{
  157. $result = $this->handler->set($this->_key($key), $value);
  158. }
  159. return $result;
  160. }
  161. public function set_org($key,$val,$prefix = '')
  162. {
  163. $this->init_master();
  164. if (!$this->enable) return false;
  165. $this->type = $prefix;
  166. $result = $this->handler->set($this->_key($key), $val);
  167. return $result;
  168. }
  169. public function get_org($key,$prefix = '')
  170. {
  171. $this->init_slave();
  172. if (!$this->enable) return false;
  173. $this->type = $prefix;
  174. $result = $this->handler->get($this->_key($key));
  175. return $result;
  176. }
  177. public function incr($key,$prefix = '')
  178. {
  179. $this->init_master();
  180. if (!$this->enable) return false;
  181. $this->type = $prefix;
  182. $key = $this->_key($key);
  183. $value = $this->handler->incr($key);
  184. return $value;
  185. }
  186. public function incrby($key,$val,$prefix = '')
  187. {
  188. $this->init_master();
  189. if (!$this->enable) return false;
  190. $this->type = $prefix;
  191. $key = $this->_key($key);
  192. $value = $this->handler->incrby($key,$val);
  193. return $value;
  194. }
  195. public function decr($key,$prefix = '')
  196. {
  197. $this->init_master();
  198. if (!$this->enable) return false;
  199. $this->type = $prefix;
  200. $key = $this->_key($key);
  201. $value = $this->handler->decr($key);
  202. return $value;
  203. }
  204. public function decrby($key,$val,$prefix = '')
  205. {
  206. $this->init_master();
  207. if (!$this->enable) return false;
  208. $this->type = $prefix;
  209. $key = $this->_key($key);
  210. $value = $this->handler->decrby($key,$val);
  211. return $value;
  212. }
  213. public function zIncrBy($key, $value, $member,$prefix='')
  214. {
  215. $this->init_master();
  216. if (!$this->enable) return false;
  217. $this->type = $prefix;
  218. $key = $this->_key($key);
  219. $result = $this->handler->zIncrBy($key,$value,$member);
  220. return $result;
  221. }
  222. public function zDelete($key, $member,$prefix='')
  223. {
  224. $this->init_master();
  225. if (!$this->enable) return false;
  226. $this->type = $prefix;
  227. $key = $this->_key($key);
  228. $result = $this->handler->zDelete($key,$member);
  229. return $result;
  230. }
  231. public function hset($name, $prefix, $data)
  232. {
  233. $this->init_master();
  234. if (!$this->enable || !is_array($data) || empty($data)) return false;
  235. $this->type = $prefix;
  236. foreach ($data as $key => $value) {
  237. if ($value[0] == 'exp') {
  238. $value[1] = str_replace(' ', '', $value[1]);
  239. preg_match('/^[A-Za-z_]+([+-]\d+(\.\d+)?)$/',$value[1],$matches);
  240. if (is_numeric($matches[1])) {
  241. $this->hIncrByFloat($name, $prefix, $key, $matches[1]);
  242. }
  243. unset($data[$key]);
  244. }
  245. }
  246. if (count($data) == 1) {
  247. $this->handler->hset($this->_key($name), key($data),current($data));
  248. } elseif (count($data) > 1) {
  249. $this->handler->hMset($this->_key($name), $data);
  250. }
  251. }
  252. public function hget($name, $prefix, $key = null) {
  253. $this->init_slave();
  254. if (!$this->enable) return false;
  255. $this->type = $prefix;
  256. if ($key == '*' || is_null($key)) {
  257. return $this->handler->hGetAll($this->_key($name));
  258. } elseif (strpos($key,',') != false) {
  259. return $this->handler->hmGet($this->_key($name), explode(',',$key));
  260. } else {
  261. return $this->handler->hGet($this->_key($name), $key);
  262. }
  263. }
  264. public function hdel($name, $prefix, $key = null)
  265. {
  266. $this->init_master();
  267. if (!$this->enable) return false;
  268. $this->type = $prefix;
  269. if (is_null($key)) {
  270. if (is_array($name)) {
  271. return $this->handler->del(array_walk($array, [__CLASS__, '_key']));
  272. } else {
  273. return $this->handler->del($this->_key($name));
  274. }
  275. } elseif (is_array($name)) {
  276. foreach ($name as $key => $value) {
  277. $this->handler->hdel($this->_key($name), $key);
  278. }
  279. return true;
  280. } else {
  281. return $this->handler->hdel($this->_key($name), $key);
  282. }
  283. }
  284. public function hIncrBy($name, $key, $value)
  285. {
  286. $this->init_master();
  287. if (!$this->enable) return false;
  288. $this->type = '';
  289. return $this->handler->hIncrBy($this->_key($name), $key, $value);
  290. }
  291. public function hIncrByFloat($name, $prefix, $key, $num = 1) {
  292. $this->init_master();
  293. if ($this->hget($name, $prefix,$key) !== false) {
  294. $this->handler->hIncrByFloat($this->_key($name), $key, floatval($num));
  295. }
  296. }
  297. public function rm($key, $type = '') {
  298. $this->init_master();
  299. if (!$this->enable) return false;
  300. $this->type = $type;
  301. return $this->handler->del($this->_key($key));
  302. }
  303. public function clear() {
  304. $this->init_master();
  305. if (!$this->enable) return false;
  306. return $this->handler->flushDB();
  307. }
  308. private function _key($str) {
  309. return $this->prefix.$this->type.$str;
  310. }
  311. public function keys($key = '')
  312. {
  313. $this->init_slave();
  314. if(!isset($key) || empty($key)) {
  315. $key = '*';
  316. }
  317. return $this->handler->keys($this->_key($key));
  318. }
  319. public function del($key){
  320. $this->init_master();
  321. if (!$this->enable) return false;
  322. return $this->handler->del($key);
  323. }
  324. public function lLen($key) {
  325. $this->init_slave();
  326. if (!$this->enable) return false;
  327. return $this->handler->lLen($key);
  328. }
  329. public function lpush($queue_name,$value)
  330. {
  331. $this->init_master();
  332. if (!$this->enable) return false;
  333. return $this->handler->lPush($queue_name, $value);
  334. }
  335. }