redis的使用场景
- 利用redis 中字符串类型完成 项目中手机验证码存储的实现
- 利用redis中字符串类型完成 具有时效性业务功能 12306等电商的订单倒计时过期功能
- 利用redis分布式集群系统中进行session共享
- 利用redis zset类型可排序的特点,可实现排行榜之类的功能
- 利用redis 实现分布式缓存
- 利用redis 实现微信小程序或者公众号的token信息
- 利用redis解决分布式集群系统中分布式锁问题
分布式缓存
缓存就是计算机内存中的数据,特点是读写快,断点立即丢失,主要用来减轻数据库访问压力,使用缓存一定是数据库中数据极少发生修改,更多用于查询这种情况
-
本地缓存:存在应用服务器内存中的数据
-
分布式缓存:存储在当前应用服务器内存之外的数据
-
集群:同一个服务的多个节点放在一起共同对外提供服务
-
分布式:有多个不同服务共同对外提供服务
自定义分布式缓存
利用mybatis自身本地缓存结合redis实现分布式缓存
a.mybatis的二级缓存是应用级别的缓存,所有会话共享,开启在mapper中使用
b.默认使用PerpetualCache类,如果需要用redis,需要实现cache接口,并在
c.自定义RedisCache实现
package com.yyb.cache;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
public class RedisCache implements Cache {
private final String id;
private RedisTemplate redisTemplate;
public RedisCache(String id) {
this.id = id;
redisTemplate = (RedisTemplate)ApplicationContextUtil.getBean("redisTemplate");
// redisTemplate.setKeySerializer(new StringRedisSerializer());
// redisTemplate.setHashValueSerializer(new StringRedisSerializer());
}
public String getId() {
return this.id;
}
public void putObject(Object o, Object o1) {
redisTemplate.opsForHash().put(id, o, o1);
}
public Object getObject(Object o) {
return redisTemplate.opsForHash().get(id, o);
}
//该方法为mybatis的保留方法,未使用
public Object removeObject(Object o) {
redisTemplate.opsForHash().delete(id, o);
return null;
}
public void clear() {
redisTemplate.opsForHash().delete(id);
}
public int getSize() {
return redisTemplate.opsForHash().size(id).intValue();
}
}
package com.yyb.cache;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static <T> T getBean(Class<T> tClass) {
return applicationContext.getBean(tClass);
}
public static Object getBean(String beanName) {
return applicationContext.getBean(beanName);
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
如果单表查询没什么问题,但是如果表之间有关联关系,比如连接查询就会存在问题,这个时候就需要使用共享缓存
缓存优化策略-对放入redis中key进行优化:key的长度不能太长,比如使用MD5处理
缓存问题
缓存穿透
客户端查询了数据库中没有的数据,导致这种情况下缓存无法利用,直接穿过redis到数据库了
解决方案:将数据库没有查询到结果也进行缓存
缓存击穿
大量请求访问热点数据,然后这个key突然失效,这些请求就会涌向数据库导致极端情况,数据库阻塞或挂起
解决方案:
1、让缓存永不过期
2、使用分布式锁,在访问数据时加锁,然后存入redis,推荐的方式
缓存雪崩
在系统运行的某一时刻,缓存全部失效,恰好这一时刻涌来了大量请求,导致缓存无法使用,请求涌向数据库导致极端情况,数据库阻塞或挂起
解决方案:
1、缓存永久存储【不推荐】
2、针对不同业务数据设置不同的超时时间