模拟php与redis穿透结果

交代背景

在学习redis的时候,主要是学会如何使用缓存,相应的问题也来了,无论是什么样的代码都会有崩的时候,这一次我们来模拟一下redis穿透。

redis穿透

redis穿透:突然大量访问缓存中不存在的key,直接去访问数据库,给数据库造成了极大的压力。

思路

因为访问的是缓存中不存在的key,那么就让这个缓存没有key好了,直接去数据库查!

实现的代码部分

require_once 'redis.php';
require_once 'model.php';
/*
*实现redis的穿透
*突然大量访问缓存中不存在的key,直接去访问数据库,给数据库造成了极大的压力(穿透)
*
*实现方式:缓存是空的,访问的时候查DB存缓存。
*
*/
function through(){
	$rconn = redisFunction::getIntance();
	$keyName = '666';
	$rconn ->deleteString($keyName);
	$result = $rconn ->getString($keyName);
	if(!$result){
		echo "缓存中没有这个key,电脑马上去数据库中取";
		return "对应的key值:".selectDB($keyName);
	}else{
		return "对应的key值:".$result;
	}
}
/*
*去数据库中寻找键对应的值
*/
function selectDB($keyName){
	$rconn = redisFunction::getIntance();
	$sql = "SELECT tit.ccontent,art.tcontent from t_title tit LEFT JOIN t_article art on art.ititleid = tit.id where tit.ccontent = '$keyName';";
	$result = PDODB::row($sql);
	//print_r($result);//Array ( [ccontent] => 第二章 [tcontent] => 地下城英雄们的传说 )
	$valName = $result["tcontent"];
	$rconn ->setString($keyName,$valName);
	return $rconn ->getString($keyName);
}
echo through();

图片

小编使用fiddler模拟了5万条访问,其中即便是200也有好多没有返回结果,是报错信息
连接mysql是单线程的,并发的时候占用资源太多是会拒绝连接的,然后就报错了。
小编使用fiddler模拟了5万条访问,其中即便是200也有好多没有返回结果,是报错信息
这个才是正确的结果
这个才是正确的结果

redis封装方法

<?php
/*
*这是一个关于redis的类文件夹
*/
class redisFunction{
	private static $rconn = false;
	private $redis;
	//构造方法
	function __construct(){
		$this->testConn();
	}
	/*
	*php连接redis
	*
	*/
	private function testConn(){
		$this->redis = new Redis();
		$this->redis->connect('127.0.0.1',6379);
		// echo "Connection to server Successful!";
		// echo "Server is running".$this->redis->ping();
	}
	/*
	*公用的静态方法
	*/
	public static function getIntance(){
	if(self::$rconn==false){
	self::$rconn=new self;
	}
	return self::$rconn;
	}
	/*
	*返回当前的DB中key的数量
	*/
	public function getNumber(){
		$count = $this->redis->dbSize();
		return $count;
	}
	/*
	*String类型(一个key对应一个value)
	*存值
	*取值
	*/
	public function setString($keyName,$valName){
		$this->redis->set($keyName,$valName);
		$this->redis->setTimeout($keyName, 3600); // x will disappear in 1 hour.
	}
	public function getString($keyName){
		$valName = $this->redis->get($keyName);
		return $valName;
	}
	/*
	*如果没有就SET,有就返回False
	*/
	public function setnxString($keyName,$valName){
		return $this->redis->setnx($keyName,$valName);
	}
	/*
	*可以接受数组
	*删除存在的key,返回剩余key的数量
	*/
	public function deleteString($keyName){
		$count = $this->redis->delete($keyName);
		return $count;
	}
	/*
	*验证指定的一个key是否存在
	*存在返回true,不存在返回false
	*/
	public function existsString($keyName){
		$result = $this->redis->exists($keyName);
		return $result;
	}
	/*
	*默认给key加1
	*也可以指定加几
	*/
	public function incrString($keyName,$num=1){
		if($num == 1){
			$this->redis->incr($keyName);
		}else{
			$this->redis->incrBy($keyName,$num);
		}
	}
	/*
	*默认给key减1
	*也可以指定减几
	*
	*/
	public function decrString($keyName,$num=1){
		if($num == 1){
			$this->redis->decr($keyName);
		}else{
			$this->redis->decrBy($keyName,$num);
		}
	}
	/*
	*返回字符串的长度
	*
	*/
	public function strlenString($keyName){
		$count = $this->redis->strlen($keyName);
		return $count;
	}
	/*
	*list类型函数
	*(一个key对应多个value,可视为是一个栈)
	*/
	
	/*
	*把值插到顶部(左侧)
	*失败返回false
	*
	*/
	public function lPushList($keyName,$member){
		$result = $this->redis->lPush($keyName,$member);
		return $result;
	}
	/*
	*添加一个字符串值到LIST容器的底部(右侧)
	*失败返回false
	*
	*/
	public function rPushList($keyName,$member){
		$result = $this->redis->rPush($keyName,$member);
		return $result;
	}
	/*
	*返回LIST顶部(左侧)的VALUE
	*
	*/
	public function lPopList($keyName){
		$result = $this->redis->lPop($keyName);
		return $result;
	}
	/*
	*返回LIST顶部(右侧)的VALUE
	*
	*/
	public function rPopList($keyName){
		$result = $this->redis->rPop($keyName);
		return $result;
	}
	/*
	*根据KEY返回该KEY代表的LIST的长度,
	*如果这个LIST不存在或者为空,那么ISIZE返回0,如果指定的KEY的数据类型不是LIST或者不为空,那么返回FALSE。
	*所以在这里多说一句,当用ISize返回判断值的时候,===就有用处了,这里FLASE和0是两个概念了。
	*/
	public function lSizeList($keyName){
		$result = $this->redis->lSize($keyName);
		return $result;
	}
	/*
	*set类型
	*一个key对用多个value,可视为一个容器
	*/
	
	/*
	*添加一个VALUE到SET容器中,如果这个VALUE已经存在于SET中,那么返回FLASE
	*具有唯一性
	*
	*/
	public function sAddSet($key,$member){
		$result = $this->redis->sAdd($key,$member);
		return $result;
	}
	/*
	*移除指定的VALUE从SET容器中
	*
	*/
	public function sRemSet($key,$member){
		$result = $this->redis->sRem($key,$member);
		return $result;
	}
	/*
	*检查VALUE是否是SET容器中的成员。
	*存在返回true,否则返回false
	*
	*/
	public function sIsMemberSet($key,$member){
		$result = $this->redis->sIsMember($key,$member);
		return $result;
	}
	/*
	*返回SET容器的成员数
	*
	*/
	public function sCardSet($key){
		$result = $this->redis->sCard($key);
		return $result;
	}
	/*
	*返回SET集合中的所有元素。
	*
	*/
	public function sMembersSet($key){
		$result = $this->redis->sMembers($key);
		return $result;
	}
	/*
	*zSet有序集合
	*具有唯一性,视为一个有序的容器
	*/
	/*
	*存值
	*
	*/
	public function zAddZset($key,$value1,$value2){
		$this->redis->zAdd($key,$value1,$value2);
	}
	/*
	*取得特定范围内的排序元素,0代表第一个元素,1代表第二个以此类推。-1代表最后一个,-2代表倒数第二个
	*
	*
	*/
	public function zRangeZSet($key,$num1=0,$num2=1,$value = true){
		if($value == true){
			$result = $this->redis->zRange($key, $num1, $num2,true); //返回$value1,$value2
		}else{
			$result = $this->redis->zRange($key, $num1, $num2); //返回$value2
		}
		return $result;
	}
	/*
	*从有序集合中删除指定的成员。
	*
	*
	*/
	public function zDeleteZSet($key,$member){
		$this->redis->zDelete($key,$member);
	}
	/*
	*返回存储在key对应的有序集合中的元素的个数。
	*
	*
	*/
	public function zSizeZSet($key){
		$result = $this->redis->zSize($key);
		return $result;
	}
	/*
	*hash类型
	*
	*/
	public function hSetHash($key1,$key2,$value){
		$this->redis->hSet($key1,$key2,$value); //hSet('h', 'key1', 'hello');
	}
	/*
	*添加一个VALUE到HASH STORE中,如果FIELD不存在
	*
	*/
	public function hSetNxHash($key1,$key2,$value){
		$this->redis->hSetNx($key1,$key2,$value); 
	}
	/*
	*取得HASH中的VALUE,如何HASH不存在,或者KEY不存在返回FLASE
	*
	*/
	public function hGetHash($key1,$key2){
		$result = $this->redis->hGet($key1,$key2);
		return $result;
	}
	/*
	*取得HASH表的长度
	*/
	public function hLenHash($key1){
		$result = $this->redis->hLen($key1);
		return $result;
	}
	/*
	*指定删除
	*/
	public function deleteHash($key1){
		$this->redis->delete($key1);
	}
	/*
	*取得HASH表中的KEYS,以数组形式返回
	*
	*/
	public function hKeysHash($key1){
		$result = $this->redis->hKeys($key1);
		return $result;
	}
	/*
	*取得HASH表中所有的VALUE,以数组形式返回
	*
	*/
	public function hValsHash($key1){
		$result = $this->redis->hVals($key1);
		return $result;
	}
	/*
	*取得整个HASH表的信息,返回一个以KEY为索引VALUE为内容的数组
	*/
	public function hGetAllHash($key1){
		$result = $this->redis->hGetAll($key1);
		return $result;
	}
	/*
	*验证HASH表中是否存在指定的KEY-VALUE,存在返回true
	*/
	public function hExistsHash($key1,$key2){
		$result = $this->redis->hExists($key1,$key2);
		return $result;
	}
	/*
	*批量取得HASH表中的VALUE
	*
	*/
	public function hmGetHash($key1,$key2){
		$result = $this->redis->hmGet($key1,$key2);
		return $result;
	}
}

?>

mysql封装方法

<?php
//这是小编在网络上寻得某位大神的作品,暂时借用一下!
class PDODB {
    private static $_instance;
    private static  $conn = null;
    private function __construct()
    {
        //链接数据库
        self::getConn();
    }

    //链接数据库
    private static  function getConn(){
        if(self::$conn === null){
            self::$conn = new PDO("mysql:host=localhost:3306;dbname=dbcanteen","root","root");
            // self::$conn = new PDO("mysql:host=127.0.0.1;Database=SiteMIS","sa","1211");
            //设置编码
            self::$conn->exec('set names utf8');
        }
        return self::$conn;
    }
	//单例模式
    private static function getInstance()
    {
        if(! (self::$_instance instanceof self) ) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }


    //查询多条语句的封装函数
    public static function getMore($field = '*', $table, $where = 1, $order = 'order by id asc', $offset = 0, $perpage = 1000000) {
        self::getInstance();
        $sql = "select $field from `$table` where $where $order limit $offset,$perpage";
        $query = self::getConn()->query($sql); //执行上面的语句
        $list = array(); //新建一个数组
        while($row = $query->fetch(PDO::FETCH_ASSOC)) {//循环news表
            $list[] = $row; //把执行出来的每一条内容赋值给list这个数组
        }
        return $list;
    }
    //获取列表
    public static function select($sql) {
        self::getInstance();
        $query = self::getConn()->query($sql); //执行上面的语句
        $list = array(); //新建一个数组
        while ($row = $query) {//循环news表
            $list[] = $row; //把执行出来的每一条内容赋值给list这个数组
        }
        return $list;
    }


    //获取列表
    public static function query($sql) {
        self::getInstance();
        $query = self::getConn()->query($sql); 
        $row = $query->fetchAll(PDO::FETCH_ASSOC);
        return $row;
    }


    //查询一条语句的封装函数
    public static function getOne($field, $table, $where) {
        self::getInstance();
        $sql = "select $field from `$table` where $where";
		//return $sql;
		//die();
        return self::getConn()->query($sql)->fetch(PDO::FETCH_ASSOC);

    }
    //查询一条记录
    public static function row($sql) {
        self::getInstance();
        return self::getConn()->query($sql)->fetch(PDO::FETCH_ASSOC);
    }
    //增加一条语句的封装函数
    //返回插入的ID
    public static function set($table, $data) {
        $str_key = '';
        $str_val = '';
        foreach ($data as $key => $val) {
            $str_key.='`' . $key . '`,';
            $str_val.="'" . $val . "',";
        }
        $str_key = substr($str_key, 0, -1);
        $str_val = substr($str_val, 0, -1);
        $sql = "insert into `$table` ($str_key) values($str_val)";
        self::getInstance();
        self::getConn()->exec($sql);
        return self::getConn()->lastInsertId();
    }

    //修改一条语句的封装函数
    //返回影响的行数
    public static function update($table, $where, $date) {
        $str_set = '';
        foreach ($date as $key => $val) {
            $str_set.="`" . $key . "`='" . $val . "',";
        }
        $str_set = substr($str_set, 0, -1);
        $sql = "update `$table` set $str_set where $where";
        self::getInstance();
        return self::getConn()->exec($sql);
    }

    //删除一条语句的封装函数
    //返回影响行数数
    public static function delete($table, $where) {
        $sql = "delete from `$table` where $where";
        self::getInstance();
        return self::getConn()->exec($sql);
    }
     
     //执行一条SQL语句
    public static function setquery($sql) {
        self::getInstance();
        $query = self::getConn()->query($sql); //执行上面的语句
        return $query;
    }
}
?>

那大家知道windows下配置phpstudy的并发上线是多少吗?
大家一起来试一试!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值