使用redis作为缓存数据库
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
缓存即将常用的不会频繁变更的数据存入内存当中,从而减少数据库压力,提升访问速率。
使用redis作为缓存技术方案,主要是redis缓存技术的特点就在于高效,因为目前涉及的数据量逐渐增多,在对于数据的存储上面和sql以及服务器资源优化上面就来的特别的重要。而redis可以帮助解决由于数据库压力造成的延迟现象,针对于很少做改变的数据并且经常使用的数据,我们可以一致性加入内存。这样可以一方面减少数据库压力,一方面提高读写效率。
缓存更新策略
更新缓存的的Design Pattern有四种:Cache aside, Read through, Write through, Write behind caching。我们使用Cache aside,其他策略介绍详见《缓存更新的套路》http://coolshell.cn/articles/17416.htm
Cache Aside Pattern
- 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
- 命中:应用程序从cache中取数据,取到后返回。
- 更新:先把数据存到数据库中,成功后,再让缓存失效。
Demo实现
下面我们从一个示例中来深入了解redis的应用,demo是在http://blog.csdn.net/u012343297/article/details/78833744的基础上编写,其他非redis部分,请移步此文。
1、在pom.xml文件添加依赖:
<properties>
<spring-boot-starter-redis-version>1.3.2.RELEASE</spring-boot-starter-redis-version>
</properties>
<!-- Spring Boot Reids 依赖 -->
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>${spring-boot-starter-redis-version}</version>
</dependency>
2、在application.propertises文件中加入redis配置
## Redis 配置
## Redis数据库索引(默认为0)
spring.redis.database=0
## Redis服务器地址
spring.redis.host=127.0.0.1
## Redis服务器连接端口
spring.redis.port=6379
## Redis服务器连接密码(默认为空)
spring.redis.password=123456
## 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
## 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
## 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
## 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
## 连接超时时间(毫秒)
spring.redis.timeout=0
参数值可以根据自己实际情况修改。
3、修改UserServiceImpl
package com.spb.SpringBootDemo.service.impl;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import com.spb.SpringBootDemo.dao.UserDao;
import com.spb.SpringBootDemo.service.IUserService;
import com.spb.SpringBootDemo.vo.User;
@Service
public class UserServiceImpl implements IUserService {
@Autowired
public UserDao userDao;
@Autowired
private RedisTemplate redisTemplate;
@Override
public void createUser(User user) {
userDao.createUser(user);
}
@Override
public List<User> findAllUser() {
return userDao.findAllUser();
}
/**
* 获取用户策略:先从缓存中获取用户,没有则取数据表中
* 数据,再将数据写入缓存
*/
@Override
public User findUserById(Long id) {
String key = "user_"+id;
ValueOperations<String,User> operations = redisTemplate.opsForValue();
boolean hasKey = redisTemplate.hasKey(key);
//缓存存在
if(hasKey){
User user = operations.get(key);
System.out.println("==========从缓存中获得数据=========");
System.out.println(user.getUsername());
System.out.println("==============================");
return user;
}else{
User user = userDao.findUserById(id);
System.out.println("==========从数据表中获得数据=========");
System.out.println(user.getUsername());
System.out.println("==============================");
//插入缓存
operations.set(key, user,5,TimeUnit.MINUTES);
return user;
}
}
/**
* 更新用户策略:先更新数据表,成功之后,再更新缓存
*/
@Override
public int updateUser(User user) {
int result = userDao.updateUser(user);
//更新成功
if(result>0){
//缓存存在?
String key = "user_"+user.getId();
boolean hasKey = redisTemplate.hasKey(key);
if(hasKey){
redisTemplate.delete(key);
System.out.println("删除缓存中的key=========>"+key);
}
}
return result;
}
/**
* 删除用户策略:删除数据表中数据,然后删除缓存
*/
@Override
public int deleteUser(Long id) {
int result = userDao.deleteUser(id);
//删除成功
if(result>0){
String key = "user_"+id;
boolean hasKey = redisTemplate.hasKey(key);
if(hasKey){
redisTemplate.delete(key);
System.out.println("删除缓存中的key=========>"+key);
}
}
return result;
}
}
4、序列化实体类User
package com.spb.SpringBootDemo.vo;
import java.io.Serializable;
public class User implements Serializable{
private String id;
private String username;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
5、测试
使用postman测试:
第一次请求,控制台输出:
第二次请求,控制台输出: