同福

做个web框架(24)——TFModel设计基于Redis的高速缓存层实现系统加速【20210113】

介绍

介绍

福哥今天要带着大家给TFPHP框架的TFModel对象进行一次大的改造,福哥要给TFModel的数据读取环节增加一个缓存层,通过这一层缓存提高系统的整体运行效率。

缓存层,其实就是数据副本,在开发里面我们称之为冗余数据,它就是将数据库里的数据取出来之后放到一个高速读写介质里面存储一份。这样以后再读取数据的时候可以优先从高速读写介质里面提取,就达到了提高读取效率的目的了。

高速读写介质,一般指的是Key-Value型的存储介质,即通过一个Key就可以直接拿到对应的Value的这种简单的数据存储引擎。在早期开发系统时候的缓存层会使用文件来存储数据,文件名就是Key,文件内容就是Value,而现如今有了更NB的工具来实现,它就是Redis数据库,使用Redis数据库的最基础数据类型就可以满足我们的需要了,Redis数据库可以设置数据的有效期,可以避免缓存数据越来越多的问题,还可以解决数据老化的问题。

我们的TFPHP框架的TFModel对象是基于MySQL实现的,模型数据存储在MySQL数据库里面,TFModel对象提供方法对数据库进CRUD操作。通常情况下,一个系统对数据的读写操作的频次对比一定的读操作大于写操作的,访问量越大的系统读操作比写操作越高,甚至可以达到上千呗、上万倍(参考论坛浏览数和跟帖数)的差距。这时候,如果我们可以在MySQL前面设置一个高速缓存层,将大量的读操作在高速缓存层处理掉,就可以避免MySQL数据库的忙碌,就可以提高系统性能了!

TFModel

路径

TFPHP\Model/TFModel

代码

a

private function a(string $a,array $b):string{
    return urlencode($a."_".json_encode($b));
}

b

private function b(string $a,array $b):?array{
    $c=$this->tables[$a];
    if($c==null){
        return null;
    }
    $d=$c['options']['cacheRedisKey'];
    $e=$this->tfphp->getDatabase()->getRedis($d);
    if($e==null){
        return null;
    }
    $f=$this->a($c['key'],$b);
    $g=$e->get($f);
    if($g!==null){
        $h=json_decode($g,true);
        if(is_array($h)){
            return $h;
        }
    }
    return null;
}

c

private function c(string $a,array $b,array $c):bool{
    $d=$this->tables[$a];
    if($d==null){
        return false;
    }
    $e=$d['options']['cacheRedisKey'];
    $f=$this->tfphp->getDatabase()->getRedis($e);
    if($f==null){
        return false;
    }
    $g=$this->a($d['key'],$b);
    $f->set($g,json_encode($c));
    $h=600;
    if(isset($d['options']['cacheRedisExpires'])){
        $h=intval($d['options']['cacheRedisExpires']);
    }
    $i=$f->expire($g,$h);
    if($i){
        return true;
    }
    return false;
}

d

private function d(string $a,array $b):bool{
    $c=$this->tables[$a];
    if($c==null){
        return false;
    }
    $d=$c['table'];
    foreach($this->tables as  $c){
        if($d!=$c['table']){
            continue;
        }
        $e=$c['options']['cacheRedisKey'];
        $f=$this->tfphp->getDatabase()->getRedis($e);
        if($f==null){
            return false;
        }
        $g=array();
        if(is_array($c['fields'])){
            foreach($c['fields'] as  $h=>$i){
                $g[$h]=$b[$h];
            }
        }
        $j=$this->a($c['key'],$g);
        $k=$f->delete($j);
        if(!$k){
            return false;
        }
    }
    return true;
}

getByTable

public function getByTable(string $table,array $values):?array{
    $a=$this->tables[$table];
    if($a==null){
        return null;
    }
    if($a['options']['cache']){
        $b=$this->b($table,$values);
        if($b!==null){
            return $b;
        }
    }
    $c=$a['options']['tfdoKey'];
    $d=$this->tfphp->getDatabase()->getTFDO($c);
    $e="select * from ".$a['table']." where ";
    $f="";
    foreach($a['fields'] as  $g=>$h){
        $f.=" and ".$g." = @".$h;
    }
    $e.=substr($f,5);
    $i=$d->fetchOne($e,$values);
    if($a['options']['cache']){
        $this->c($table,$values,$i);
    }
    return $i;
}

update

public function update(string $table,array $data,?array $dataType,array $values):bool{
    $a=$this->tables[$table];
    if($a==null){
        return false;
    }
    $b=$a['options']['tfdoKey'];
    $c=$this->tfphp->getDatabase()->getTFDO($b);
    if($c==null){
        return false;
    }
    $d="";
    $e=array();
    if(is_array($a['fields'])){
        $f=0;
        foreach($a['fields'] as  $g=>$h){
            $d.=" AND ".$g." = @".$h;
            $e[$g]=$values[$f];
            $f++;
        }
        if($d!=""){
            $d=substr($d,5);
        }
    }
    $i=$a['table'];
    $j=$c->update($i,$data,$dataType,$d,$e);
    if($j){
        if($a['options']['cache']){
            $this->d($table,$data);
        }
        return $j;
    }
    else{
        $k=$c->getLastErrcode();
        $l=$c->getLastErrmsg();
        throw new\Exception($l,$k);
    }
}

delete

public function delete(string $table,array $values):bool{
    $a=$this->tables[$table];
    if($a==null){
        return false;
    }
    $b=$a['options']['tfdoKey'];
    $c=$this->tfphp->getDatabase()->getTFDO($b);
    if($c==null){
        return false;
    }
    $d="";
    $e=array();
    if(is_array($a['fields'])){
        $f=0;
        foreach($a['fields'] as  $g=>$h){
            $d.=" AND ".$g." = @".$h;
            $e[$g]=$values[$f];
            $f++;
        }
        if($d!=""){
            $d=substr($d,5);
        }
    }
    $i=$a['table'];
    $j=$c->delete($i,$d,$e);
    if($j){
        return $j;
    }
    else{
        $k=$c->getLastErrcode();
        $l=$c->getLastErrmsg();
        throw new\Exception($l,$k);
    }
}

讲解

TFModel

a

建立缓存Key名称

b

从高速缓存层读取数据

c

向高速缓存层写入数据

d

将数据从高速缓存层理删除

getByTable

在读取数据的时候优先从高速缓存层获取数据,如果缓存不存在再去数据库里获取数据,最后再把数据库里的数据存到高速缓存层里

update

当数据发生变化的时候要清理掉所有相关的缓存数据

delete

当数据被删除的时候要清理掉所有相关的缓存数据

使用

代码

be794ccdfdb0ffb6.jpg

总结

今天福哥带着童鞋们给TFPHP框架的TFModel对象的数据读取功能增加了一个高速缓存设计,使用TFModel提供的CRUD相关方法对数据进行操作的时候,可以借助基于Redis数据库的高速缓存层大大地提高系统的运行效率,访问量越大效果越明显~~