缓存穿透解决方案

概念

缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。

解决方案

假设缓存数据库是Redis,比如我们查询用户45709823的用户信息,
不管我们是否查到用户,我们都会这么设置

原理

缓存存取逻辑一般比较简单。

  1. 查缓存,缓存存在直接返回
  2. 缓存不存在,查数据库获取数据(这一步会有问题),然后写入缓存。

其中第二步的查数据库获取数据会有问题,假设当前有个人,知道你用户id没有负数开头的,我直接请求你获取用户信息接口,http:/api.com?uid=-123456

这时候你没有任何防缓存穿透的策略,
第一步:查uid=-123456的缓存,缓存不存在
第二步:查数据库uid=-123456的记录,当然肯定也查不到,查不到就不会写入缓存。

现在别人写个脚本开1w个线程请求你接口,相当于你现在的缓存是没有用的,请求全部落到DB中查询不存在的数据,当前你数据库就处于缓存穿透的情况中。压力一大DB就会宕机。

这时候有个非常简单的办法,不管请求数据是否存在,你都要写入缓存一个唯一标识,比如0,查不到数据你也会写入标识,下次别人重复请求接口,他拿到的是缓存数据,这时候代码中可以判断是否有用户信息,如果没有用户信息,只有防缓存穿透的标识,这时候你可以扔报错或者其他逻辑。

代码示例

// 缓存穿透
$user = $redis->get('uid_xxx');
if (!$user) {
	$value = $db->query("select * from user = 'uid_xxx'");
	if ($user) {
		$redis->set('uid_xxx', $value);
	}
}
// 防止缓存穿透
$user = $redis->get('uid_xxx');
if (!$user) {
    $value = [
       '_' => [0],
	];
	$row = $db->query("select * from user = 'uid_xxx'");
	if ($user) {
	 	$value['user'] = $row;
	}
	$redis->set('uid_xxx', $value);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值