集成Redis缓存
本章主要介绍如何安装Redis缓存、Redis缓存5种基本数据类型的增删改查、Spring Boot中如何集成Redis缓存以及如何使用Redis缓存用户数据等内容。
1.Redis缓存介绍
1.1 Redis概述
Redis是一个基于内存的单线程高性能key-value型数据库,读写性能优异。和Memcached缓存相比,Redis支持丰富的数据类型,包括string(字符串)、list(链表)、set(集合)、zset(sorted set有序集合)和hash(哈希类型)。因此Redis在企业中被广泛使用。
1.2 Redis服务器安装
Redis项目本身是不支持Windows的,但是Microsoft开发技术小组针对Win64开发和维护了Windows端口,所以可以在网络上下载Redis的Windows版本。具体步骤如下:
- 打开官方网站http://redis.io/,单击Download
![](https://i-blog.csdnimg.cn/blog_migrate/af10e0ad2d4824bd01f3d12289159039.png)
- 在弹出的页面中,找到Learn more选项,并单击进入。
![](https://i-blog.csdnimg.cn/blog_migrate/1edbc7b30ff7fdb40cedb6e2b3a0e26e.png)
- 在弹出的页面中选择【releases】选项。
![](https://i-blog.csdnimg.cn/blog_migrate/a038124deda39a52b9853a0a3a0c9334.png)
- 在弹出的界面中选择Redis3.0.504这个版本,选择其他版本也可以,单击【Redis-x64-3.0.504.zip】下载Redis安装包。
![](https://i-blog.csdnimg.cn/blog_migrate/7d40ce575e9b6f3eee5f9e675724a56c.png)
- 解压下载的安装包【Redis-x64-3.0.504.zip】,双击【redis-server.exe】,Redis服务器就运行起来了,同时可以看到Redis启动成功的界面,如图所示。
![](https://i-blog.csdnimg.cn/blog_migrate/83f3d14143e608a056a5c8f4ced654f7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/673360100547fe5dc1e1e3e0c5e22ae3.png)
1.3 Redis缓存测试
Redis安装成功之后,可以在安装包里找到Redis客户端程序redis-cli.exe,双击redis-cli.exe,打开Redis客户端界面。
![](https://i-blog.csdnimg.cn/blog_migrate/5eeca9b5bd686a9c623be7af029db665.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8c3f50b4c32b08b8b4218ab531a7b01e.png)
下面就使用Redis客户端对Redis的几种数据类型做基本的增删改查操作练习。
1.3.1 字符串类型的增删改查
![](https://i-blog.csdnimg.cn/blog_migrate/7c5a2eb3913387f618d0019d9e4accb1.png)
1.3.2 List集合的增删改查
![](https://i-blog.csdnimg.cn/blog_migrate/3753cfc494af8e262f72a1f9ff1bb898.png)
1.3.3 Set集合的增删改查
![](https://i-blog.csdnimg.cn/blog_migrate/59cb5f2d99f78f628542101b3e87bb6e.png)
1.3.4 Hash集合的增删改查
![](https://i-blog.csdnimg.cn/blog_migrate/6a7443f3731b25fe92c8c9291d352ec1.png)
1.3.5 SortedSet集合的增删改查
![](https://i-blog.csdnimg.cn/blog_migrate/a70b599952329e883ea400e8bccb96d3.png)
2.Spring Boot集成Redis缓存
2.1 Spring Boot缓存支持
在Spring Boot中提供了强大的基于注解的缓存支持,可以通过注解配置的方式低侵入地给原有Spring应用增加缓存功能,提高数据访问的性能。Spring Boot为我们配置了多个CacheManager的实现,可以根据具体的项目要求使用相应的缓存技术。
![](https://i-blog.csdnimg.cn/blog_migrate/33390ba4fad93b2ea2519fcdf35435b2.png)
从图可知,Spring Boot支持许多类型的缓存,比如EhCache、JCache、Redis等。在不添加任何额外配置的情况下,Spring Boot默认使用SimpleCacheConfiguration,考虑到Redis缓存在企业中被广泛使用,故选择用Redis缓存来进行讲解。
2.2 引入依赖
在Spring Boot中集成Redis,首先需要在pom.xml文件中引入所需的依赖,具体代码如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.3 添加缓存配置
在pom文件引入Redis所需的依赖之后,需要在application.properties文件中添加如下的配置信息:
### redis缓存配置
### 默认redis数据库为db0
spring.redis.database=0
### 服务器地址,默认为localhost
spring.redis.host=localhost
### 链接端口,默认为6379
spring.redis.port=6379
### redis密码默认为空
spring.redis.password=
2.4 测试用例开发
在application.properties配置文件中添加完Redis配置之后,在测试类DemoApplicationTests.java中继续添加如下的代码:
@Resource
private RedisTemplate redisTemplate;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Test
public void testRedis() {
//增key:name, value:ay
redisTemplate.opsForValue().set("name","ay");
String name = (String)redisTemplate.opsForvalue().get("name");
System.out.printIn(name);
//删除
redisTemplate.delete("name");
//更新
redisTemplate.opsForvalue().set("name","al");
//查询
name = stringRedisTemplate.opsForValue().get("name");
System.out.printIn(name);
}
RedisTemplate和StringRedisTemplate都是Spring Data Redis提供的两个模板类用来对数据进行操作,其中StringRedisTemplate只针对键值都是字符串的数据进行操作。在应用启动的时候,Spring会初始化这两个模板类,通过@Resource注解注入即可使用。
RedisTemplate和StringRedisTemplate除了提供opsForValue方法用来操作简单属性数据之外,还提供了以下数据访问方法。
- opsForList:操作含有list的数据。
- opsForSet:操作含有set的数据。
- opsForZSet:操作含有ZSet(有序set)的数据。
- opsForHash:操作含有hash的数据。
当我们的数据存放到Redis的时候,键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用JdkSerializationRedisSerializer,而StringRedisTemplate默认使用StringRedisSerializer。
2.5 测试
上节测试用例代码开发完成之后,运行单元测试用例,除了可以在控制台查看打印结果信息和在Redis客户端查看数据之外,还可以使用RedisClient客户端工具查看Redis缓存数据库中的数据。RedisClient客户端软件可以到网络上下载,并安装到自己的操作系统中。安装完成之后,可以看到如图所示的界面。
![](https://i-blog.csdnimg.cn/blog_migrate/1c18f338a9fd7bff3d54a947d6575a9b.png)
可以看到Redis默认有16个数据库,客户端与Redis建立连接后会自动选择0号数据库。通过该客户端可以清楚地查看Redis数据库中存放的数据情况,同时可以在客户端中对数据进行增删改查等操作,方便使用。
3.Redis缓存在Spring Boot中的使用
3.1 监听器Listener开发
在上一章,我们已经简单地开发好AyUserListener监听器类,并在上下文启动时打印信息。在本节中,我们想在上下文初始化的方法中,加载数据库中的所有用户数据,并存放到Redis缓存中。之所以要把用户数据存放到缓存中,是因为用户的数据属于变动不大的数据,适合存放到缓存中,在应用需要获取用户数据时,可以直接到Redis缓存中获取,不用到数据库中获取数据库连接查询数据,提高数据的访问速度。具体代码如下:
@WebListener
public class AyuserListener implements ServletContextListener {
@Resource
private RedisTemplate redisTemplate;
@Resource
private AyUserService ayUserService;
private static final String ALL_USER ="ALL_USER_LIST";
@override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//查询数据库所有的用户
List<AyUser> ayUserList = ayUserService.findAll();
//清除缓存中的用户数据
redisTemplate.delete(ALL_USER);
//将数据存放到Redis缓存中
redisTemplate.opsForList().leftPushAll(ALL _USER, ayUserList);
//真实项目中需要注释掉,查询所有的用户数据
List<AyUser> queryUserList = redisTemplate.opsForList().range(ALL_USER, 0,-1);
System.out.println("缓存中目前的用户数有:"+ queryUserList.size()+"人");
System.out. println("ServletContext上下文初始化");
}
@Override
public void contextDestroyed (ServletContextEvent servletContextEvent){
System.out.printIn("ServletContext上下文销毁");
}
}
- redisTemplate.opsForList().leftPushAll:查询缓存中所有的用户数据,ALL_USER键若不存在,会创建该键及与其关联的List,之后再将参数中的ayUserList从左到右依次插入。
- redisTemplate.opsForList().range:取链表中的全部元素,其中0表示第一个元素,-1表示最后一个元素。
当我们的数据存放到Redis的时候,键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用JdkSerializationRedisSerializer,而StringRedisTemplate默认使用StringRedisSerializer。所以我们需要让用户类AyUser(/src/main/java/com.example.demo.model)实现序列化接口Serializable,具体代码如下:
@Entity
@Table(name = "ay_user")
public class AyUser implements Serializable{
//省略代码
}
3.2 项目启动缓存数据
开发好AyUserListener监听器类和AyUser用户类,重新启动项目,这时候数据库表ay_user中的所有数据都会加载到Redis缓存中。在contextInitialized方法中进行断点调试,出现如图所示的图片,可见代码数据已经成功地被加载到缓存中。我们也可以用RedisClient客户端软件来查看用户数据是否存放到缓存中。
![](https://i-blog.csdnimg.cn/blog_migrate/69138e070a6182ec34aeaa612f5e45ab.png)
3.3 更新缓存数据
项目启动加载所有用户数据到缓存之后,需要修改AyUserServiceImpl中的接口,比如findById、Save、Delete等方法。因为如果在Redis缓存中查询不到数据,那么就需要到数据库中查询,如果能够在数据库中查询到数据,除了返回数据之外,还需要把数据更新到缓存中。这样再次查询数据时,就不需要到数据库中查询数据。这里主要对方法findById进行修改,AyUserServiceImpl中具体需要修改的代码如下:
//省略代码
@Service
public class AyUserServiceImpl implements AyUserService {
@Resource(name = "ayUserRepository")
private AyUserRepository ayUserRepository;
@Resource
private RedisTemplate redisTemplate;
private static final String ALL USER ="ALL_USER_LIST";
@Override
public AyUser findById(String id){
//step.1查询 Redis缓存中的所有数据
List<AyUser> ayUserList= redisTemplate.opsForList.range(ALL_USER,0,-1);
if(ayUserList != null & ayUserList.size() > 0){
for(AyUser user:ayUserList){
if (user.getId().equals(id)){
return user;
}
}
}
//step.2查询数据库中的数据
AyUserayuser ayuserRepository.findById(id).get();
if(ayUser != null){
//step.3将数据插入到 Redis缓存中
redisTemplate.opsForList(leftPush(ALL_USER, ayUser);
}
return ayuser;
//省略代码
}
}
对于Save、Delete等方法的修改,思路是一样的,这里就不一一重复赘述,读者可自己尝试实现。虽然引入Redis缓存用户数据可以提高访问性能,但是带来的代码复杂度也是可想而知的。所以在工作中,需要权衡性能和代码的复杂度,根据具体的业务场景加以选择,不可滥用缓存。
3.4 测试
在测试类MySpringBootApplicationTests下继续添加如下的测试方法:
@Test
public void testFindById(){
Long redisUserSize = OL;
//查询id=1的数据,该数据存在于Redis缓存中
AyUser ayUser = ayUserService.findById("1");
redisUsersize = redisTemplate.opsForList().size("ALL_USER_LIST");
System.out.println("目前缓存中的用户数量为:"+ redisUsersize);
System.out.printIn("--->>>id:"+ ayUser.getId()+"name:"+ ayUser. getName());
//查询id=2的数据,该数据存在于Redis缓存中
AyUser ayUserl = ayUserService.findById("2");
redisUsersize = redisTemplate.opsForList().size("ALL_USER_LIST");
System.out.println("目前缓存中的用户数量为:"+ redisUsersize);
System.out.printIn("--->>i:"+ ayUser1.getId()+"name:"+ ayUserl.getName());
//查询id=4的数据,不存在于 Redis缓存中,存在于数据库中,所以会把数据库查询的数据更新到缓存中
AyUser ayUser3 = ayUserService.findById("4");
System.out.println ("--->> id:" + ayUser3.getId()+ "name:"+ ayUser3. getName());
redisUserSize = redisTemplate.opsForList().size("ALL_USER_LIST");
System.out.println("目前缓存中的用户数量为:"+ redisUsersize);
}
代码开发完成之后,重新启动项目,数据库中的3条数据会重新被添加到Redis缓存中。项目启动成功之后,我们往数据库表ay_user中添加id为4的第4条数据。
最后执行单元测试方法testFindById(),在Intellij IDEA的控制台中会打印如下的信息:
目前缓存中的用户数量为:3
-->>>id:name:阿毅
目前缓存中的用户数量为:3
--->>>id:name阿兰
--->>>id: 4 name: test
目前缓存中的用户数量为:4