Memcached.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace think\cache\driver;
  12. use think\cache\Driver;
  13. class Memcached extends Driver
  14. {
  15. protected $options = [
  16. 'host' => '127.0.0.1',
  17. 'port' => 11211,
  18. 'expire' => 0,
  19. 'timeout' => 0, // 超时时间(单位:毫秒)
  20. 'prefix' => '',
  21. 'username' => '', //账号
  22. 'password' => '', //密码
  23. 'option' => [],
  24. 'serialize' => true,
  25. ];
  26. /**
  27. * 架构函数
  28. * @access public
  29. * @param array $options 缓存参数
  30. */
  31. public function __construct($options = [])
  32. {
  33. if (!extension_loaded('memcached')) {
  34. throw new \BadFunctionCallException('not support: memcached');
  35. }
  36. if (!empty($options)) {
  37. $this->options = array_merge($this->options, $options);
  38. }
  39. $this->handler = new \Memcached;
  40. if (!empty($this->options['option'])) {
  41. $this->handler->setOptions($this->options['option']);
  42. }
  43. // 设置连接超时时间(单位:毫秒)
  44. if ($this->options['timeout'] > 0) {
  45. $this->handler->setOption(\Memcached::OPT_CONNECT_TIMEOUT, $this->options['timeout']);
  46. }
  47. // 支持集群
  48. $hosts = explode(',', $this->options['host']);
  49. $ports = explode(',', $this->options['port']);
  50. if (empty($ports[0])) {
  51. $ports[0] = 11211;
  52. }
  53. // 建立连接
  54. $servers = [];
  55. foreach ((array) $hosts as $i => $host) {
  56. $servers[] = [$host, (isset($ports[$i]) ? $ports[$i] : $ports[0]), 1];
  57. }
  58. $this->handler->addServers($servers);
  59. $this->handler->setOption(\Memcached::OPT_COMPRESSION, false);
  60. if ('' != $this->options['username']) {
  61. $this->handler->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
  62. $this->handler->setSaslAuthData($this->options['username'], $this->options['password']);
  63. }
  64. }
  65. /**
  66. * 判断缓存
  67. * @access public
  68. * @param string $name 缓存变量名
  69. * @return bool
  70. */
  71. public function has($name)
  72. {
  73. $key = $this->getCacheKey($name);
  74. return $this->handler->get($key) ? true : false;
  75. }
  76. /**
  77. * 读取缓存
  78. * @access public
  79. * @param string $name 缓存变量名
  80. * @param mixed $default 默认值
  81. * @return mixed
  82. */
  83. public function get($name, $default = false)
  84. {
  85. $this->readTimes++;
  86. $result = $this->handler->get($this->getCacheKey($name));
  87. return false !== $result ? $this->unserialize($result) : $default;
  88. }
  89. /**
  90. * 写入缓存
  91. * @access public
  92. * @param string $name 缓存变量名
  93. * @param mixed $value 存储数据
  94. * @param integer|\DateTime $expire 有效时间(秒)
  95. * @return bool
  96. */
  97. public function set($name, $value, $expire = null)
  98. {
  99. $this->writeTimes++;
  100. if (is_null($expire)) {
  101. $expire = $this->options['expire'];
  102. }
  103. if ($this->tag && !$this->has($name)) {
  104. $first = true;
  105. }
  106. $key = $this->getCacheKey($name);
  107. $expire = $this->getExpireTime($expire);
  108. $value = $this->serialize($value);
  109. if ($this->handler->set($key, $value, $expire)) {
  110. isset($first) && $this->setTagItem($key);
  111. return true;
  112. }
  113. return false;
  114. }
  115. /**
  116. * 自增缓存(针对数值缓存)
  117. * @access public
  118. * @param string $name 缓存变量名
  119. * @param int $step 步长
  120. * @return false|int
  121. */
  122. public function inc($name, $step = 1)
  123. {
  124. $this->writeTimes++;
  125. $key = $this->getCacheKey($name);
  126. if ($this->handler->get($key)) {
  127. return $this->handler->increment($key, $step);
  128. }
  129. return $this->handler->set($key, $step);
  130. }
  131. /**
  132. * 自减缓存(针对数值缓存)
  133. * @access public
  134. * @param string $name 缓存变量名
  135. * @param int $step 步长
  136. * @return false|int
  137. */
  138. public function dec($name, $step = 1)
  139. {
  140. $this->writeTimes++;
  141. $key = $this->getCacheKey($name);
  142. $value = $this->handler->get($key) - $step;
  143. $res = $this->handler->set($key, $value);
  144. return !$res ? false : $value;
  145. }
  146. /**
  147. * 删除缓存
  148. * @access public
  149. * @param string $name 缓存变量名
  150. * @param bool|false $ttl
  151. * @return bool
  152. */
  153. public function rm($name, $ttl = false)
  154. {
  155. $this->writeTimes++;
  156. $key = $this->getCacheKey($name);
  157. return false === $ttl ?
  158. $this->handler->delete($key) :
  159. $this->handler->delete($key, $ttl);
  160. }
  161. /**
  162. * 清除缓存
  163. * @access public
  164. * @param string $tag 标签名
  165. * @return bool
  166. */
  167. public function clear($tag = null)
  168. {
  169. if ($tag) {
  170. // 指定标签清除
  171. $keys = $this->getTagItem($tag);
  172. $this->handler->deleteMulti($keys);
  173. $this->rm($this->getTagKey($tag));
  174. return true;
  175. }
  176. $this->writeTimes++;
  177. return $this->handler->flush();
  178. }
  179. /**
  180. * 缓存标签
  181. * @access public
  182. * @param string $name 标签名
  183. * @param string|array $keys 缓存标识
  184. * @param bool $overlay 是否覆盖
  185. * @return $this
  186. */
  187. public function tag($name, $keys = null, $overlay = false)
  188. {
  189. if (is_null($keys)) {
  190. $this->tag = $name;
  191. } else {
  192. $tagName = $this->getTagKey($name);
  193. if ($overlay) {
  194. $this->handler->delete($tagName);
  195. }
  196. if (!$this->has($tagName)) {
  197. $this->handler->set($tagName, '');
  198. }
  199. foreach ($keys as $key) {
  200. $this->handler->append($tagName, ',' . $key);
  201. }
  202. }
  203. return $this;
  204. }
  205. /**
  206. * 更新标签
  207. * @access protected
  208. * @param string $name 缓存标识
  209. * @return void
  210. */
  211. protected function setTagItem($name)
  212. {
  213. if ($this->tag) {
  214. $tagName = $this->getTagKey($this->tag);
  215. if ($this->has($tagName)) {
  216. $this->handler->append($tagName, ',' . $name);
  217. } else {
  218. $this->handler->set($tagName, $name);
  219. }
  220. $this->tag = null;
  221. }
  222. }
  223. /**
  224. * 获取标签包含的缓存标识
  225. * @access public
  226. * @param string $tag 缓存标签
  227. * @return array
  228. */
  229. public function getTagItem($tag)
  230. {
  231. $tagName = $this->getTagKey($tag);
  232. return explode(',', trim($this->handler->get($tagName), ','));
  233. }
  234. }