有些业务经常访问数据库表数据,但是访问数据库表是有IO消耗的,特别是成百上千万的访问量时,系统更加受不住,会造成一部分用户获取不到响应,交互体验差。
这时候就需要提升系统性能,以便改善响应速率,最高效方便的就是缓存,现在就使用redis实现高性能缓存,将我们业务中最常用的数据缓存到redis中,则我们不需要访问数据库,直接获取内存中的缓存,效率高很多。
就是访问save和update方法时,将数据放到redis里缓存起来,访问delete方法时删掉redis中的数据,访问get方法的时候直接从redis中获取数据,没有的时候才从数据库中获取数据。
来看一下一个最简版的缓存实现
demo1
public class NewsServiceImpl implements NewsService {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private Redisson redisson;
@Autowired
private NewsDao newsDao;
private final static String CACHE_NEWS_PRE = "cache:newes";
@Override
public NewsEntity get(long id) {
String news = (String)redisTemplate.opsForValue().get(CACHE_NEWS_PRE + id);
if (StringUtils.isNotBlank(news)){
NewsEntity entity = JSON.parseObject(news, NewsEntity.class);
return entity;
}
NewsEntity dbEntity = newsDao.getOne(id);
if (dbEntity != null) redisTemplate.opsForValue().set(CACHE_NEWS_PRE + id, dbEntity);
return dbEntity;
}
@Override
public NewsEntity insert(NewsEntity entity) {
NewsEntity news = newsDao.save(entity);
redisTemplate.opsForValue().set(CACHE_NEWS_PRE + news.getId(), JSONObject.toJSONString(news));
return news;
}
@Override
public NewsEntity update(NewsEntity entity) {
NewsEntity news = newsDao.save(entity);
redisTemplate.opsForValue().set(CACHE_NEWS_PRE + news.getId(), JSONObject.toJSONString(news));
return news;
}
@Override
public void delete(long id) {
newsDao.deleteById(id);
redisTemplate.delete(CACHE_NEWS_PRE + id);
}
}
这种代码只能应付偶尔使用缓存的情况,高并发高访问下就不中用了,那就改进一下。
明眼的一看就知道有线程安全问题,缓存读写不一致。缓存也没有做管理,一直占用内存,如果新浪微博的数据,缓存一直不做清理,上亿的数据,redis不得炸了,先来处理下这个问题,当我们读写这个数据时,给它设置超时时间,那么一直被访问的数据就会被保留在redis中,不被访问的慢慢的就会过期了。
demo2
// 所有设置缓存的地方都加了超时时间,我假设定了1天超时
@Override
public NewsEntity get(long id) {
String news = (String)redisTemplate.