ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 缓存插件 `ESD` 已默认启用本插件。 ## 插件使用 缓存可以使用注解的形式,在需要加缓存的函数中添加相关注释。 >[danger] **添加注解的函数不能为`private`。** 引用 ~~~ use ESD\Plugins\Cache\Annotation\Cacheable; ~~~ ## Cacheable 方法 >[info]如果缓存不存在就创建,如果存在就直接返回。 参数说明 > ### $key = ""; 代表需要删除的命名空间下唯一的缓存`key`。 使用`php`语法,`$p[0]` 获取对应参数,可以增加前缀,其值最终将作为表达式在 `eval` 中执行。 ~~~ /** * @Cacheable(key="$p[0]", namespace="user") * @param $id * @return array */ ~~~ ~~~ /** * @Cacheable(key="'user_'.$p[0]", namespace="user") * @param $id * @return array */ ~~~ ~~~ /** * @Cacheable(key="'user_'.$p[0]->user", namespace="user") * @param $id * @return array */ ~~~ > ### $time = 0; 缓存时间 0 代表使用默认时间,-1 代表无限时间,对有 `namespace` 的无效,`namespace`底层使用`hset`存储,无法单独设置时间。同时如果使用默认时间底层会对缓存超时设置一个`20%`以内的浮动。如果不需要此特性请设置该参数或覆盖默认设置。 ~~~ /** * @Cacheable(key="$p[0]", time="3000") * @param $id * @return array */ ~~~ > ### namespace= "" 对缓存进行分组,分组的数据底层存放`hset`,所以不能设置过期时间。后期删除可以针对`namespace`批量删除。 ~~~ /** * @Cacheable(key="$p[0]", namespace="user") * @param $id * @return array */ ~~~ > ### $condition = ""; 有的时候我们可能并不希望缓存一个方法所有的返回结果。 通过 `condition `属性可以实现这一功能。`condition`属性默认为空,表示将缓存所有的调用情形。 其值是通过PHP表达式来指定的,当为true时表示进行缓存处理; 当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。 ~~~ /** * @Cacheable(key="'cache_test'.$p[0]", namespace="test", condition="$p[0] >= 5") */ ~~~ 使用例子 ~~~ /** * get操作创建缓存 * @Cacheable(key="'cache_test'.$p[0]", namespace="test", condition="$p[0] >= 5") * @param $id * @return array */ protected function cacheTest($id){ $res = $this->mysql->query("SHOW GLOBAL STATUS LIKE '%connections%'"); $this->log->debug('cacheTest db', $res); return $res; } ~~~ ## CacheEvict >[info]无论缓存是否存在,始终清除缓存 引用 ~~~ use GoSwoole\Plugins\Cache\Annotation\CacheEvict; ~~~ 除了Cacheable方法之外的参数还有以下参数 > ### $allEntries = false; 标记是否删除命名空间下所有缓存,默认为`false` > ### $beforeInvocation = false; 在调用方法之前清除缓存中的指定元素,默认为`false` 默认设置下,清除操作是在对应方法成功执行之后触发的,如果方法因为抛出异常而未能成功返回时也不会触发清除操作。使用`beforeInvocation`可以改变触发清除操作的时间,当我们指定该属性值为`true`时,会在调用该方法之前清除缓存中的指定元素。 使用例子 ~~~ /** * update删除缓存 * @CacheEvict(key="'cache_test'.$p[0]",namespace="test", allEntries="true", beforeInvocation="true") * @param $id * @return array */ public function updateTest($id){ //do something return $res; } ~~~ ### CachePut >[info]不检查缓存是否存在,始终生成缓存 引用 ~~~ use GoSwoole\Plugins\Cache\Annotation\CachePut; ~~~ 参数与 Cacheable 一致。 对于使用 `@Cacheable` 标注的方法,在每次执行前都会检查 Cache 中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。 `@CachePut` 也可以声明一个方法支持缓存功能。与 `@Cacheable `不同的是使用`@CachePut` 标注的方法在执行前`不会去检查`缓存中是否存在之前执行过的结果, 而是`每次都会`执行该方法,并将执行结果以键值对的形式存入指定的缓存中。 ## 配置项 无需配置即可直接使用,如果需要覆盖默认配置,需要将被覆盖的部分参数增加到 `application.yml`文件中。下面依次说明相关配置, > 如无特别说明,以下列出的均为默认值,不改配置无需修改配置文件。 ~~~ cache: timeout: 1800 (缓存超时时间) db: default (使用的redis连接标识) cacheStorageClass: ESD\Plugins\Cache\RedisCacheStorage(使用的缓存驱动) lock_timeout: 0 (是否开启缓存读锁等待。此为高级功能下面详细说明) lock_wait: 500(读取锁等待重试间隔) lock_alive: 20000(锁存活时间) ~~~ ## lock_timeout 配置 如果设置为0则不启用读写锁,开启后写入缓存时会进行加锁,避免高并发缓存穿透。 高并发建议开启该设置,并且调高 redis 连接池以及 redis 的连接数。 如果每秒并发2000,超时设置为3秒,那么会有2000个连接等待。 如果秒级 set 建议设置 3000 如果几百毫秒 set 建议设置 1000 如果不到100毫秒 set 建议设置 500 注意只有 Cacheable 方法支持该功能 >[danger] 如果锁超时,同样会直接访问数据库获取数据。 ## lockWait 配置 读取锁等待重试时长,单位(毫秒)。 每隔 lockWait 重试,如果缓存写入需要秒级,建议调整 lockWait 为 500 毫秒以上 如果缓存写入需要 几百毫秒级,建议使用默认 100 毫秒 如果缓存写入需要 一百毫秒以内,建议设置 50 毫秒 注意: 此值设置的太低会严重增加 redis get 负载, 如果每秒并发 2000,超时设置3秒,默认锁等待100 毫秒,那么最差会有6万get操作 注意:等待时长不要超过lockTimeout,否则会浪费协程资源。 ## lockAlive 配置 死锁过期时间 单位(毫秒) 注意:lockAlive 一定要大于lock_timeout 时间,否则如果锁释放了还没有写入缓存同样会造成缓存穿透。 注意:配置在 application.yml 中,大写字符需要以下划线的形式覆盖默认配置。