PHP 使用 Redis 实现分页

讲一下为什么使用redis实现分页。
1.后端写接口的时候,维护数据表的curd吗,缓存key总被更新,这样一来有一批key未被使用, 就被refresh掉了。
2.许多表跨库查询的时候 ,查询出来的结果集, 需要分页的时候再次查询比较耗时从而增加了数据库的负担。
下面说一下实现思路 :把维护结果集中id 为分值存入指定key的有序集合中,这样这个指定key的有序集合,就会维护一个按分值大小排序的有序集合,值得注意的是这个有序集合一定设置过期时间和长度,不然的话无限长的集合和不过期key会造成内存使用不合理 ,虽然redis里有key过期设置,不过更喜欢代码掌握自己掌控范围内。
代码实现:
namespace app\Constants\Nomal;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
class RedisList{
   // 添加一条数据到redis中
    public function zAdd($key,array $value){
        return Redis::zadd($key,$value);
    }
    // 从Redis返回一条数据
    public function zRange($key,$start,$end,$withScores){
        return  Redis::zRange($key,$start,$end,$withScores);
    }
    // Redis 返回一条数据从大小返回数据
    public function zrevRange ($key,$start,$end,$withScores){
        return  Redis::ZREVRANGE($key,$start,$end,$withScores);
    }
    // Redis 返回某个数据 按分数正序排序 //ZRANGEBYSCORE
    public function  zRangByScore($key,$start,$end,$withScores){
        return Redis::ZRANGEBYSCORE($key,$start,$end,$withScores);
    }
    // Redis 返回数据按分数倒叙排序 // ZREVRANGEBYSCORE
    public function zRevRangBySore($key,$start,$end,$withScores){
        return Redis::ZREVRANGEBYSCORE($key,$start,$end,$withScores);
    }

    // 删除某个成员的值
    public function zRem($key,$member){
        return Redis::zRem($key,$member);
    }
    // 返回zset集合中所有元素的个数
    public function zSize($key){

        return Redis::zcard($key);
    }
    // 返回比元素$member分数大的元素的个数
    public function zRevRank($key,$member){

        return Redis::zRevRank($key,$member);
    }
    // 如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment
    public function zIncrBy($key,$increment,$member){

        return Redis::zIncrBy($key,$increment,$member);
    }
    // 求有序集合的并集
    public function zUnion($output,$zsetkey){

        return Redis::zUnion($output,$zsetkey);
    }
    //求有序集合的交集
    public function zInter($output,$zsetkey){

        return Redis::zInter($output,$zsetkey);
    }
    // redis 分页处理
    public function limitAndPage($pageIndex,$pageNum){
        return array('pageIndex'=>$pageIndex-1,'pageNumber'=>$pageIndex*$pageNum-1);
    }
    // redis 队列操作 入队列
    public function lPush($key,$value){
        return Redis::LPUSH($key,$value);
    }
    // redis 根据索引取数据
    public function lIndex($key,$position){
        return Redis::lIndex($key,$position);
    }
    // redis list维护一个长度为100000的队列
    public function lTrim($key,$start=0,$stop=100000){
        return Redis::lTrim($key,$start,$stop);
    }
    // 设置key的过期时间 现在设置的是一个月的时间 做二级缓存使用
    public function expire($key,$timesec =0){
        if($timesec == 0){
            $expire_time = 0<$timesec? $timesec: strtotime(date('Y-m-d')) + 2592000 - time();
        }else{
            $expire_time = $timesec;
        }
        return Redis::expire($key,$expire_time);
    }
    // 设置zset的长度
    public function SetZsetTime($key,$data,$lenth =4){
        if($this->zSize($key)>$lenth){
            Redis::zremrangebyrank($key,0,count($data)-1);
        }
    }
    public function getListInfoByCondition($key,$start,$end,array $limit,$sort = 'asc'){
       if($sort == 'desc'){
          $pageNum = $limit['limit'][0]*$limit['limit'][1];
          $limit['limit'][0] = $this->zSize($key)-$pageNum;
          // 本方法只使用于app分页 上一页 下一页 不支持跳页查询
       }
       return $sort == 'desc'?array_reverse($this->zRangByScore($key,$start,$end,$limit)):$this->zRangByScore($key,$start,$end,$limit);
    }
    // 添加一条数据
    public function addOneInfo($key,array $data){
       if(Redis::exists($key)){
           if(count($data)>4){
               return false;
           }
           $ret = $this->zAdd($key,$data);
           $this->SetZsetTime($key,$data);
           return $ret;
       }else{
          $this->expire($key,60);
          return $this->zAdd($key,$data);
       }
    }
    // 更新一条数据
    public function updateOneById($key,$id,$data){
       $this->deleteOneById($key,$id);
       return $this->zAdd($key,$data);
    }
    // 删除一条数据
    public function deleteOneById($key,$id){
        return Redis::zremrangebyscore($key,$id,$id);
    }
    // 获取一条数据
    public function getOneInfoById($key,$id){
        return $this->zRangByScore($key,$id,$id,array('withScores'=>''));
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
附言 1  ·  4年前

缓存修改 更新也可以使用 消息队列完成

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 3
public function getListInfoByCondition($key,$start,$end,array $limit,$sort = 'asc')

这里面的 $limit 是啥呢😂。 排版有点乱而且没有phpdoc...

4年前 评论
lar_cainiao (楼主) 4年前
lar_cainiao (楼主) 4年前
Lichmaker (作者) 4年前
JerryMan

我有一个问题啊:如果在redis缓存列表数据过期前,我在浏览第三页数据,到我请求第四页数据的时候redis缓存的数据已经由于过期被清理掉了怎么办

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!