No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Driver.php 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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;
  12. use think\Container;
  13. /**
  14. * 缓存基础类
  15. */
  16. abstract class Driver
  17. {
  18. /**
  19. * 驱动句柄
  20. * @var object
  21. */
  22. protected $handler = null;
  23. /**
  24. * 缓存读取次数
  25. * @var integer
  26. */
  27. protected $readTimes = 0;
  28. /**
  29. * 缓存写入次数
  30. * @var integer
  31. */
  32. protected $writeTimes = 0;
  33. /**
  34. * 缓存参数
  35. * @var array
  36. */
  37. protected $options = [];
  38. /**
  39. * 缓存标签
  40. * @var string
  41. */
  42. protected $tag;
  43. /**
  44. * 序列化方法
  45. * @var array
  46. */
  47. protected static $serialize = ['serialize', 'unserialize', 'think_serialize:', 16];
  48. /**
  49. * 判断缓存是否存在
  50. * @access public
  51. * @param string $name 缓存变量名
  52. * @return bool
  53. */
  54. abstract public function has($name);
  55. /**
  56. * 读取缓存
  57. * @access public
  58. * @param string $name 缓存变量名
  59. * @param mixed $default 默认值
  60. * @return mixed
  61. */
  62. abstract public function get($name, $default = false);
  63. /**
  64. * 写入缓存
  65. * @access public
  66. * @param string $name 缓存变量名
  67. * @param mixed $value 存储数据
  68. * @param int $expire 有效时间 0为永久
  69. * @return boolean
  70. */
  71. abstract public function set($name, $value, $expire = null);
  72. /**
  73. * 自增缓存(针对数值缓存)
  74. * @access public
  75. * @param string $name 缓存变量名
  76. * @param int $step 步长
  77. * @return false|int
  78. */
  79. abstract public function inc($name, $step = 1);
  80. /**
  81. * 自减缓存(针对数值缓存)
  82. * @access public
  83. * @param string $name 缓存变量名
  84. * @param int $step 步长
  85. * @return false|int
  86. */
  87. abstract public function dec($name, $step = 1);
  88. /**
  89. * 删除缓存
  90. * @access public
  91. * @param string $name 缓存变量名
  92. * @return boolean
  93. */
  94. abstract public function rm($name);
  95. /**
  96. * 清除缓存
  97. * @access public
  98. * @param string $tag 标签名
  99. * @return boolean
  100. */
  101. abstract public function clear($tag = null);
  102. /**
  103. * 获取有效期
  104. * @access protected
  105. * @param integer|\DateTime $expire 有效期
  106. * @return integer
  107. */
  108. protected function getExpireTime($expire)
  109. {
  110. if ($expire instanceof \DateTime) {
  111. $expire = $expire->getTimestamp() - time();
  112. }
  113. return $expire;
  114. }
  115. /**
  116. * 获取实际的缓存标识
  117. * @access protected
  118. * @param string $name 缓存名
  119. * @return string
  120. */
  121. protected function getCacheKey($name)
  122. {
  123. return $this->options['prefix'] . $name;
  124. }
  125. /**
  126. * 读取缓存并删除
  127. * @access public
  128. * @param string $name 缓存变量名
  129. * @return mixed
  130. */
  131. public function pull($name)
  132. {
  133. $result = $this->get($name, false);
  134. if ($result) {
  135. $this->rm($name);
  136. return $result;
  137. } else {
  138. return;
  139. }
  140. }
  141. /**
  142. * 如果不存在则写入缓存
  143. * @access public
  144. * @param string $name 缓存变量名
  145. * @param mixed $value 存储数据
  146. * @param int $expire 有效时间 0为永久
  147. * @return mixed
  148. */
  149. public function remember($name, $value, $expire = null)
  150. {
  151. if (!$this->has($name)) {
  152. $time = time();
  153. while ($time + 5 > time() && $this->has($name . '_lock')) {
  154. // 存在锁定则等待
  155. usleep(200000);
  156. }
  157. try {
  158. // 锁定
  159. $this->set($name . '_lock', true);
  160. if ($value instanceof \Closure) {
  161. // 获取缓存数据
  162. $value = Container::getInstance()->invokeFunction($value);
  163. }
  164. // 缓存数据
  165. $this->set($name, $value, $expire);
  166. // 解锁
  167. $this->rm($name . '_lock');
  168. } catch (\Exception $e) {
  169. $this->rm($name . '_lock');
  170. throw $e;
  171. } catch (\throwable $e) {
  172. $this->rm($name . '_lock');
  173. throw $e;
  174. }
  175. } else {
  176. $value = $this->get($name);
  177. }
  178. return $value;
  179. }
  180. /**
  181. * 缓存标签
  182. * @access public
  183. * @param string $name 标签名
  184. * @param string|array $keys 缓存标识
  185. * @param bool $overlay 是否覆盖
  186. * @return $this
  187. */
  188. public function tag($name, $keys = null, $overlay = false)
  189. {
  190. if (is_null($name)) {
  191. } elseif (is_null($keys)) {
  192. $this->tag = $name;
  193. } else {
  194. $key = $this->getTagkey($name);
  195. if (is_string($keys)) {
  196. $keys = explode(',', $keys);
  197. }
  198. $keys = array_map([$this, 'getCacheKey'], $keys);
  199. if ($overlay) {
  200. $value = $keys;
  201. } else {
  202. $value = array_unique(array_merge($this->getTagItem($name), $keys));
  203. }
  204. $this->set($key, implode(',', $value), 0);
  205. }
  206. return $this;
  207. }
  208. /**
  209. * 更新标签
  210. * @access protected
  211. * @param string $name 缓存标识
  212. * @return void
  213. */
  214. protected function setTagItem($name)
  215. {
  216. if ($this->tag) {
  217. $key = $this->getTagkey($this->tag);
  218. $this->tag = null;
  219. if ($this->has($key)) {
  220. $value = explode(',', $this->get($key));
  221. $value[] = $name;
  222. if (count($value) > 1000) {
  223. array_shift($value);
  224. }
  225. $value = implode(',', array_unique($value));
  226. } else {
  227. $value = $name;
  228. }
  229. $this->set($key, $value, 0);
  230. }
  231. }
  232. /**
  233. * 获取标签包含的缓存标识
  234. * @access protected
  235. * @param string $tag 缓存标签
  236. * @return array
  237. */
  238. protected function getTagItem($tag)
  239. {
  240. $key = $this->getTagkey($tag);
  241. $value = $this->get($key);
  242. if ($value) {
  243. return array_filter(explode(',', $value));
  244. } else {
  245. return [];
  246. }
  247. }
  248. protected function getTagKey($tag)
  249. {
  250. return 'tag_' . md5($tag);
  251. }
  252. /**
  253. * 序列化数据
  254. * @access protected
  255. * @param mixed $data
  256. * @return string
  257. */
  258. protected function serialize($data)
  259. {
  260. if (is_scalar($data) || !$this->options['serialize']) {
  261. return $data;
  262. }
  263. $serialize = self::$serialize[0];
  264. return self::$serialize[2] . $serialize($data);
  265. }
  266. /**
  267. * 反序列化数据
  268. * @access protected
  269. * @param string $data
  270. * @return mixed
  271. */
  272. protected function unserialize($data)
  273. {
  274. if ($this->options['serialize'] && 0 === strpos($data, self::$serialize[2])) {
  275. $unserialize = self::$serialize[1];
  276. return $unserialize(substr($data, self::$serialize[3]));
  277. } else {
  278. return $data;
  279. }
  280. }
  281. /**
  282. * 注册序列化机制
  283. * @access public
  284. * @param callable $serialize 序列化方法
  285. * @param callable $unserialize 反序列化方法
  286. * @param string $prefix 序列化前缀标识
  287. * @return $this
  288. */
  289. public static function registerSerialize($serialize, $unserialize, $prefix = 'think_serialize:')
  290. {
  291. self::$serialize = [$serialize, $unserialize, $prefix, strlen($prefix)];
  292. }
  293. /**
  294. * 返回句柄对象,可执行其它高级方法
  295. *
  296. * @access public
  297. * @return object
  298. */
  299. public function handler()
  300. {
  301. return $this->handler;
  302. }
  303. public function getReadTimes()
  304. {
  305. return $this->readTimes;
  306. }
  307. public function getWriteTimes()
  308. {
  309. return $this->writeTimes;
  310. }
  311. public function __call($method, $args)
  312. {
  313. return call_user_func_array([$this->handler, $method], $args);
  314. }
  315. }