我们在做项目时,通常都要考虑一个问题,网站首页每天都会有大量的人访问,对数据库造成很大的访问压力,甚至是瘫痪。如何解决呢? 我们通常的解决方法有两种:1.网页静态化。2.数据缓存。
网页静态化技术可以参照:网页静态化技术之Freemarker
下面我们就来介绍一下数据缓存。
redis:
redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写。企业开发通常采用Redis来实现缓存。
现在大部分公司做项目时,使用的都为Spring Data Redis 。
Spring Data Redis:
Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,是在redis基础上的封装是开发者能够更简单的来操作redis,reids底层开发包(Jedis, JRedis, and RJC)。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。
spring-data-redis针对jedis提供了如下功能:
1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2.针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作
项目中添加配置文件:applicationContext-redis.xml
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
代码中使用redis缓存时只需要注入即可。
@Autowired
private RedisTemplate redisTemplate;
redis缓存中存在的问题:
缓存穿透:
什么是缓存穿透?就是指在查询一个一定不存在的数据时,由于缓存是不命中时需要从数据库中查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求时都要到数据库中去查询,造成的缓存穿透。
解决方法:
- 对所有可能查询的参数以hash形式存储,并在控制层校验,不符合则直接丢弃。
- 可以采取一个更简单粗暴的方法,如果查询一个返回的数据为空(不管是数据不存在还是系统异常),我们仍然把这个数据存储到缓存中,但它的过期时间会很短,最长不超过五分钟。
缓存雪崩:
什么是缓存雪崩?如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,那么就造成啦缓存雪崩。
这个没有完美的解决方法,可以分析用户的行为,尽量让失效时间点均匀分布。大多数设计者都会考虑用加锁胡或者队列的方式保证缓存的单线程,从而避免失效时大量的并发请求落在底层存储系统上。
解决方案:
- 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。
- 可以通过缓存的reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存。
- 不同的key,设置不同的过期时间,让缓存失效的时间尽量均匀一点
- 做二级缓存或者双缓存策略。