摘要
工作经常会碰到类似只保留最新的多少条的问题。直接删除此缓存、或者任由缓存里的数据增加,只取XX条的解决方案都过于粗糙。抽象出此问题,也就是如何维持一个固定大小的缓存。
解决方案1.0
每次添加新元素后,都会判断此缓存中的元素个数,如果大于XX则删除多余元素
$this->redis->lPush($key, $data);
$count = $this->redis->lLen($key);
$limit = 200;
if($count > $limit) {
$this->redis->rPop($key);
}
解决方案2.0
上述方案,需要与redis通讯至少2次,至多3次,当然可以用事务把前两个redis操作合成一次通讯,但那也至多会有2次,能不能都是一次通讯呢?
我们努力的方向就是如何把元素个数判断给去掉,于是我们可以这么使用redis截取命令LTRIM与 ZREMRANGEBYRANK
/**
* list添加元素维持固定长度,左侧入栈,右侧出栈
* @param string $key
* @param string $data 添加的元素
* @param int $length 固定长度
* @return bool/array
*/
public function lPushLimit($key, $data, $length)
{
if(!$this->redis || empty($data) || $length <= 0){
return false;
}
return $this->redis->multi()
->lPush($key, $data)
->lTrim($key, 0, $length-1)
->exec();
}
/**
* list添加元素维持固定长度,右侧入栈,左侧出栈
* @param string $key
* @param string $data 添加的元素
* @param int $length 固定长度
* @return bool/array
*/
public function rPushLimit($key, $data, $length)
{
if(!$this->redis || empty($data) || $length <= 0){
return false;
}
return $this->redis->multi()
->rPush($key, $data)
->lTrim($key, -$length, -1)
->exec();
}
/**
* zset添加元素时维持固定长度
* @param string $key
* @param array $data 添加的元素 [6, 'sixth']/[6, 'sixth', 7, 'seventh']
* @param int $length 固定长度
* @param bool $pop_min 出栈元素是否为最小score值
* @return bool/array
*/
public function zAddLimit($key, $data, $length, $pop_min = true)
{
if(!$this->redis || empty($data) || $length <= 0){
return false;
}
if ($pop_min) {
$start = 0;
$stop = -$length-1;
} else {
$start = $length;
$stop = PHP_INT_MAX;
}
return $this->redis->multi()
->zAdd($key, ...$data)
->zRemRangeByRank($key, $start, $stop)
->exec();
}