Redis缓存雪崩、缓存击穿、缓存穿透

直接在代码中解释了

redis.php

<?php

// 一个单例模式连接数据库文件
require_once "./single.php";

/**
 * Class Redisavalanche
 * 缓存雪崩 (大量的redis在同一时间全部失效了,导致大量请求打到关系型数据库中)
 * 解决办法:
 * set设置redis的时候,加随机时间值,保证大量的redis不会同一时间失效(见 randomTime)
 * 设置双缓存策略,就像下面方法avalanche中一样
 */
class Redisavalanche extends Single{

    private $redis;

    private $redis_key = 'uc.0100';

    private $redis_key_cache = 'list_cache';

    private $expire = 30;

    public function __construct()
    {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', '6379');
        $this->redis->auth('123456');
    }

    public function avalanche()
    {
    	// 双缓存
        $cache_result = $this->redis->get($this->redis_key_cache);
        $result = $this->redis->get($this->redis_key);
        if(!$cache_result) {
            $this->redis->set($this->redis_key_cache, 1, $this->expire);
            $data = Single::singleTest()->query('select * from sns_page');
            foreach($data as $val) {
                $this->redis->set($val['PAGE_NAME'], $val['PAGE_URL'], $this->expire * 2);
            }
        }
        return $result;
    }
	
	// 给key加过期随机时间
    public function randomTime()
    {
        $cache_result = $this->redis->get($this->redis_key);
        if(!$cache_result) {
            $data = Single::singleTest()->query('select * from sns_page');
            foreach($data as $val) {
                $this->redis->set($val['PAGE_NAME'], $val['PAGR_URL'], $this->expire + mt_rand(10,100));  // 包含10和100
            }
        }
    }
}



/**
 * Class Redisbreakdown
 * 缓存击穿 (一个热点数据,在redis缓存失效的瞬间,大量请求打到关系型数据库)
 * 解决:
 * redis 互斥锁, 大量请求访问时,允许第一个请求去读取数据库,并把数据放到缓存中,后面请求去读缓存
 * 设置redis key不过期,但是需要后面自己去更新key的值
 */
class Redisbreakdown extends Single {
    private $redis;

    private $redis_key = 'uc.0100';

    private $setnx_key = 'n';

    private $expire = 30;

    public function __construct()
    {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', '6379');
        $this->redis->auth('123456');
    }

    public function breakdown()
    {
        $redis_val = $this->redis->get($this->redis_key);
        if(!$redis_val) {
        	// 互斥锁
            if($this->redis->setnx($this->setnx_key, 1, $this->expire)) {
                $data = Single::singleTest()->query('select * from sns_page where PAGE_ID=879');
                $this->redis->set($this->redis_key, $data['PAGE_URL'], $this->expire);
                $this->redis->del($this->setnx_key);
            } else {
            	// 重新取
                sleep(10);
                self::breakdown();
            }
        }
    }
}


/**
 * Class Redispenetrate
 * 缓存穿透 (请求缓存和数据库中都不存在的数据时,会造成堵塞, 比如取id=负数时)
 * 解决:
 * 布隆过滤器
 * 条件限制判断
 * 设置空值缓存,时间短点
 */
class Redispenetrate extends Single {
    private $redis;

    private $redis_key = 'uc.0100';

    private $expire = 10;

    public function __construct()
    {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', '6379');
        $this->redis->auth('123456');
    }
	
	// 把空值缓存起来 时间设置短一点
    public function penetrate()
    {
        $result = $this->redis->get($this->redis_key);
        if(!isset($result)) {
            $data = Single::singleTest()->query('select * from sns_page where PAGE_ID=-1');
            if(!$data) {
                $result = [];
                $redis_val = $this->redis->set($this->redis_key, $result, $this->expire);
            }
        }
        return $result;
    }
}




single.php

<?php

/**
 * Class Single
 * 单例模式
 * 三私一公
 */
class Single {

    private function __construct(){}

    private function __clone(){}

    private static $instance;

    static public function singleTest()
    {
        if(!self::$instance) {
            try {
                self::$instance = new PDO('mysql:host=localhost;dbname=pia_demo;port=3307', 'root', '123456');
            } catch (PDOException $e) {
                die($e->getMessage());
            }
        }
        return self::$instance;
    }

    public static function getData()
    {
        $data = self::singleTest()->query('select * from sns_page');
        var_dump($data);
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值