spring中的redis使用
RedisTemplate
- 存入
```java //注入 @Autowired private RedisTemplateredisTemplate;
String redisKey = getForbiddenUser(phone); long timeout = Convert.toLong(forbiddenUser.getEndTime()) - System.currentTimeMillis(); String redisValue = forbiddenUser.getViolationCount().toString();
redisTemplate.opsForValue().set(redisKey, redisValue, timeout, TimeUnit.SECONDS);
- 取出
redisTemplate.opsForValue().get(redisKey, redisValue, timeout, TimeUnit.SECONDS);
- 判断数据
redisTemplate.hasKey(redisKey) ```
缓存击穿
- 原因:一个非常热点key过期,在key失效的瞬间,持续的高并发穿破缓存,直接访问数据库,并设置到缓存中,导致性能下降
- 解决方案:
- 永不过期
面对突然暴增的热点,可以设置一个算法,当访量达到一定数值之后,将其设置为永不过期 - 加锁排队
如果从redis中获取不到数据,就加锁(同步锁或者分布式锁),只让一个线程访问数据库,访问之后存储进redis中,之后的请求就可以直接从redis中获取数据
- 永不过期
缓存雪崩
- 原因:1.大量缓存集中过期 2.缓存服务器宕机
从而导致大量请求直接访问数据库,数据库因为压力过大而宕机 - 解决方案:
- 缓存集中过期:加锁排队,随机失效时间(不集中失效)
- 服务器宕机:redis高可用(集群之类的)
缓存穿透
- 原因:请求的数据数据库中不存在,缓存中也不存在(用户伪造大量请求)
- 解决方案:
- 参数校验
- 缓存空对对象
不管数据存不存在,从数据库中取出后都存入redis,并设置过期时间
- 布隆过滤器
布隆过滤器就是一种数据结构,从数据库中查询结束后,不存在的数据就存储进布隆过滤器(黑名单),之后这个请求就不再通过
为什么使用redis缓存,而不是map、guava?
- 缓存分为本地缓存和分布式缓存,redis属于分布式缓存,map和guava是属于本地缓存,redis可以单独部署
- redis可以使用持久化,而本地缓存程序重启之后就清空了,生命周期随着jvm的销毁而结束
- redis存储的数据量比较大,能存2.5亿个key,单个key的存储上线是512m
- redis运行与内存,存储速度快