Redis教程

Redis问题

本文主要是介绍Redis问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

Redis问题

缓存问题

缓存是在第一次加载的数据进行复用,将数据存放指定地点以便下次加载使用。可防止多访问同一 数据库 而产生的堵塞,也能减轻 数据库 的压力!

Java缓存

  • 虚拟机缓存(ehcache、JBoss Cache)
  • 分布式缓存(redis、memcache)
  • 数据库缓存

缓存雪崩

原因

原有缓存失效(或者未加载到缓存中),因此 访问过程会跨越缓存直接访问 数据库,这一过程很有可能会导致 数据库 宕机(CPU、内存 高负载)

解决方案

原有缓存失效后,可通过 加锁 或 队列 进行控制 数据库的线程数量。失效期间 尽快修复 缓存,否则 用户访问会堵塞

加锁

public Users getByUsers(Long id) {
	// 1.先查询redis
	String key = this.getClass().getName() + "-" + Thread.currentThread().getStackTrace()[1].getMethodName()+ "-id:" + id;
	String userJson = redisService.getString(key);
	if (!StringUtils.isEmpty(userJson)) {
		Users users = JSONObject.parseObject(userJson, Users.class);
		return users;
	}
	Users user = null;
	try {
		lock.lock();
		// 查询db
		user = userMapper.getUser(id);
		redisService.setSet(key, JSONObject.toJSONString(user));
	} catch (Exception e) {
        
	} finally {
		lock.unlock(); // 释放锁
	}
	return user;
}

缓存穿透

原因

当用户查询指定数据 且 数据库 中恰好也没有,此时缓存自然也不会有。这样就导致 重复查询 都会访问数据库,类似的查询都会绕过缓存直接查数据库!

解决方案

  • 如果首次 数据库 访问查询的数据为空,可直接设置一个默认值进行缓存,这样下次有相同的访问,就不会继续访问 数据库
  • 也可把空结果,进行缓存,这样下次有相同的访问,就不会继续访问 数据库
public String getByUsers2(Long id) {
	// 1.先查询redis
	String key = this.getClass().getName() + "-" + Thread.currentThread().getStackTrace()
[1].getMethodName()+ "-id:" + id;
	String userName = redisService.getString(key);
	if (!StringUtils.isEmpty(userName)) {
		return userName;
	}
	System.out.println("######开始发送数据库DB请求########");
	Users user = userMapper.getUser(id);
	String value = null;
	if (user == null) {
		// 标识为null
		value = "";
	} else {
		value = user.getName();
	}
	redisService.setString(key, value);
	return value;
}

缓存击穿

原因

在某一时间点 突然以超高并发进行访问 过期的key,导致 缓存被击穿
突然高频访问的key 称为 热点数据

解决方案

  • 使用锁,单机 synchronizedlock 等,分布式用 分布式锁
  • 缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存

分布式锁问题

死锁

原因

通过setnx命令,创建的key-value值,若未设置有效期;或者是持有锁的客户端崩溃未释放锁。都很有可能会卡住

解决方案

GET命令 查看锁是否超时,超时则可使用 getset命令 获取锁

这篇关于Redis问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!