开心一笑
【跟老公冷战几天了,一句话也没说过。
早上老公是在忍不住了,跟我说:老婆,你的气消了吧。
我没理他,
他急了说:你生气这么多天了,就是充气的,也早就没气了。
我。。】

新书购买

戳图购买 >>>

7.1 Redis缓存介绍

7.1.1 Redis概述

Redis是一个基于内存的,单线程高性能key-value型数据库,读写性能优异。和Memcached缓存相比,Redis支持丰富的数据类型,包括string(字符串)、list(链表)、set(集合)、zset(sorted set有序集合)和hash(哈希类型)。因此Redis在企业中被广泛使用。

7.1.2 Redis服务器安装

Redis项目本身是不支持Window,但是Microsoft开放技术小组开发和维护这个Windows端口针对Win64。所以我们可以在网络上下载Redis的Window版本。具体步骤如下:
打开官网http://redis.io/,点击Download,具体如图7-1所示。

图7-1 Redis下载首页
在弹出的页面中,找到Learn more选项,并点击进入,具体如图7-2所示。


图7-2 点击Learn more链接
在弹出的页面中选择【releases】选项,具体如图7-3所示。

图7-3 选择Download ZIP下载Redis

在弹出的界面中选择Redis3.0.504这个版本,选择其它版本也可以,点击【Redis-x64-3.0.504.zip】下载Redis安装包,如图7-4所示。


图7-4 下载Redis 3.0.504安装包
解压下载的安装包【Redis-x64-3.0.504.zip】,双击【redis-server.exe】,Redis服务就运行起来了,如图7-5所示。同时我们可以看到Redis启动成功的界面,如图7-6所示。


图7-5 启动redis服务器


图7-6 redis启动成功界面

7.1.3 Redis缓存测试

Redis安装成功之后,我们可以在安装包里找到Redis客户端程序redis-cli.exe,如图7-7所示,双击redis-cli.exe,打开Redis客户端界面,如果7-8所示。


图7-7 启动redis客户端 图7-8 redis启动成功界面

下面就使用Redis客户端对Redis的几种数据类型做基本的增删改查操作练习,具体代码如下:
字符串类型的增删改查:

###增加一个值key为name,value为ay
127.0.0.1:6379> set name 'ay'
OK
###查询name的值
127.0.0.1:6379> get name
"ay"
###更新name的值为al
127.0.0.1:6379> set name 'al'
OK
###查询name的值
127.0.0.1:6379> get name
"al"
###删除name的值
127.0.0.1:6379> del name
(integer) 1
###查询是否存在name,0代表不存在
127.0.0.1:6379> exists name
(integer) 0
127.0.0.1:6379>
List集合的增删改查:
###添加key为user_list,value为’ay’,’al’的list集合
127.0.0.1:6379> lpush user_list 'ay' 'al'
(integer) 2
###查询key为user_list的集合
127.0.0.1:6379> lrange user_list 0 -1
1) "al"
2) "ay"
###往list尾部添加love元素
127.0.0.1:6379> rpush user_list 'love'
(integer) 3
###往list头部添加hope元素
127.0.0.1:6379> lpush user_list 'hope'
(integer) 4
###查询key为user_list的集合
127.0.0.1:6379> lrange user_list 0 -1
1) "hope"
2) "al"
3) "ay"
4) "love"
###更新index为0的值
127.0.0.1:6379> lset user_list 0 'wish'
OK
###查询key为user_list的集合
127.0.0.1:6379> lrange user_list 0 -1
1) "wish"
2) "al"
3) "ay"
4) "love"
###删除index为0的值
127.0.0.1:6379> lrem user_list 0 'wish'
(integer) 1
###查询key为user_list的集合
127.0.0.1:6379> lrange user_list 0 -1
1) "al"
2) "ay"
3) "love"
127.0.0.1:6379>

Set集合的增删改查:

###添加key为user_set,value为"ay" "al"  "love"的集合
127.0.0.1:6379> sadd user_set "ay" "al"  "love"
(integer) 3
###查询key为user_set集合
127.0.0.1:6379> smembers user_set
1) "al"
2) "ay"
3) "love"
###删除value为love,返回1表示删除成功,0表示失败
127.0.0.1:6379> srem user_set 'love'
(integer) 1
###查询set集合所有值
127.0.0.1:6379> smembers user_set
1) "al"
2) "ay"
###添加love元素,set集合是没有顺序的,所以无法判断添加到那个位置
127.0.0.1:6379> sadd user_set 'love'
(integer) 1
###查询set集合所有值,发现添加到第二个位置
127.0.0.1:6379> smembers user_set
1) "al"
2) "love"
3) "ay"
###添加love元素,由于set集合已经存在,返回0代表添加不成功,但是不会报错
127.0.0.1:6379> sadd user_set 'love'
(integer) 0

Hash集合的增删改查:

###清除数据库
127.0.0.1:6379> flushdb
OK
###创建hash,key为user_hset,字段为user1,值为ay
127.0.0.1:6379> hset user_hset "user1"  "ay"
(integer) 1
###往key为user_hset添加字段为user2,值为al
127.0.0.1:6379> hset user_hset "user2"  "al"
(integer) 1
###查询user_hset字段长度
127.0.0.1:6379> hlen user_hset
(integer) 2
###查询user_hset所有字段
127.0.0.1:6379> hkeys user_hset
1) "user1"
2) "user2"
###查询user_hset所有值
127.0.0.1:6379> hvals user_hset
1) "ay"
2) "al"
###查询字段user1的值
127.0.0.1:6379> hget user_hset "user1"
"ay"
###获取key为user_hset所有的字段和值
127.0.0.1:6379> hgetall user_hset
1) "user1"
2) "ay"
3) "user2"
4) "al"
###更新字段user1的值为new_ay
127.0.0.1:6379> hset user_hset "user1" "new_ay"
(integer) 0
###更新字段user2的值为new_al
127.0.0.1:6379> hset user_hset "user2" "new_al"
(integer) 0
###获取key为user_hset所有的字段和值
127.0.0.1:6379> hgetall user_hset
1) "user1"
2) "new_ay"
3) "user2"
4) "new_al"
###删除字段user1和值
127.0.0.1:6379> hdel user_hset user1
(integer) 1
###获取key为user_hset所有的字段和值
127.0.0.1:6379> hgetall user_hset
1) "user2"
2) "new_al"
127.0.0.1:6379>

SortedSet集合的增删改查

###清除数据库
127.0.0.1:6379> flushdb
OK
###SortedSet集合添加ay元素,分数为1
127.0.0.1:6379> zadd user_zset  1 "ay"
(integer) 1
###SortedSet集合添加al元素,分数为2
127.0.0.1:6379> zadd user_zset  2 "al"
(integer) 1
###SortedSet集合添加love元素,分数为3
127.0.0.1:6379> zadd user_zset  3 "love"
(integer) 1
###按照分数由小到大查询user_zset集合元素
127.0.0.1:6379> zrange user_zset 0 -1
1) "ay"
2) "al"
3) "love"
###按照分数由大到小查询user_zset集合元素
127.0.0.1:6379> zrevrange user_zset 0 -1
1) "love"
2) "al"
3) "ay"
###查询元素ay的分数值
127.0.0.1:6379> zscore user_zset "ay"
"1"
###查询元素love的分数值
127.0.0.1:6379> zscore user_zset "love"
"3"

7.2 Spring Boot集成Redis缓存

7.2.1 Spring Boot缓存支持

在Spring Boot中提供了强大的基于注解的缓存支持,可以通过注解配置方式,低侵入的给原有Spring应用增加缓存功能,提高数据访问性能。Spring Boot为我们配置了多个CacheManager的实现,我们可以根据具体的项目要求使用相应的缓存技术。具体如图7-9所示。


图7-9 Spring Boot缓存配置类

从图7-9可知,Spring Boot支持许多类型的缓存,比如:EhCache、JCache、Redis等。在不添加任何额外配置的情况下,Spring Boot默认使用SimpleCacheConfiguration,考虑到Redis缓存在企业中被广泛使用,故选择用Redis缓存来进行讲解。

7.2.2 引入依赖

在Spring Boot中集成Redis,首先需要在pom.xml文件中引入所需的依赖,具体代码如下:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

7.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=

7.2.4 测试用例开发

在application.properties配置文件中添加完Redis配置之后,我们在测试类MySpringBootApplicationTests.java继续添加如下的代码:

@Resourceprivate RedisTemplate redisTemplate;@Resourceprivate StringRedisTemplate stringRedisTemplate;@Testpublic void testRedis(){//增 key:name,value:ayredisTemplate.opsForValue().set("name","ay");String name = (String)redisTemplate.opsForValue().get("name");System.out.println(name);//删除redisTemplate.delete("name");//更新redisTemplate.opsForValue().set("name","al");//查询name = stringRedisTemplate.opsForValue().get("name");System.out.println(name);}

RedisTemplate和StringRedisTemplate都是Spring Data Redis为我们提供的两个模板类用来对数据进行操作,其中StringRedisTemplate只针对键值都是字符串的数据进行操作。在应用启动的时候,Spring会为我们初始化这两个模板类,通过@Resource注解注入即可使用。

RedisTemplate和StringRedisTemplate除了提供opsForValue方法用来操作简单属性数据之外,还提供了以下其它主要数据访问方法:
1)opsForList:操作含有list的数据。
2)opsForSet:操作含有set的数据。
3)opsForZSet:操作含有ZSet(有序set)的数据。
4)opsForHash:操作含有hash的数据。

当我们的数据存放到Redis的时候,键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用JdkSerializationRedisSerializer,而StringRedisTemplate默认使用StringRedisSerializer。

7.2.5 测试

7.2.4节测试用例代码开发完成之后,我们运行单元测试用例,除了可以在控制台查看打印结果信息和在redis客户端查看数据之外,我们还可以使用Redis Client客户端工具查看Redis缓存数据库中的数据。Redis Client客户端软件,大家可以到网络上下载,并安装到自己的操作系统中。 安装完成之后,可以看到如图7-10所示的界面。


图7-10 redis client界面

在图7-10中,我们可以看到Redis默认有16个数据库,客户端与Redis建立连接后会自动选择0号数据库。通过该客户端,我们可以清楚的查看Redis数据库中存放的数据情况,同时可以在客户端中对数据进行增删改查等操作,方便使用。

7.3 Redis缓存在Spring Boot中使用

7.3.1 监听器Listener开发

在6.2.2节当中,我们已经简单的开发好AyUserListener监听器类,并在上下文启动时候打印信息。在这节当中,我们想在上下文初始化的方法中,加载数据库中的所有用户数据,并存放到Redis缓存中。之所以要把用户数据存放到缓存中,是因为用户的数据属于变动不大的数据,适合存放到缓存中,在应用需要获取用户数据时,可以直接到Redis缓存中获取,不用到数据库中获取数据库连接查询数据,提高数据的访问速度。具体代码如下:

/*** 描述:监听器* @author Ay* @date   2017/11/4*/
@WebListener
public class AyUserListener implements ServletContextListener {@Resourceprivate RedisTemplate redisTemplate;@Resourceprivate AyUserService ayUserService;private static final String ALL_USER = "ALL_USER_LIST";@Overridepublic 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上下文初始化");
}@Overridepublic void contextDestroyed(ServletContextEvent servletContextEvent) {System.out.println("ServletContext上下文销毁");}
}

redisTemplate.opsForList().leftPushAll:查询缓存中所有的用户数据, ALL_USER键若不存在,会创建该键及与其关联的List,之后再将参数中的ayUserList从左到右依次插入。
redisTemplate.opsForList().range:取链表中的全部元素,其中0表示第一个元素,-1表示最后一个元素。
在7.2.3节中,我们已经提到,当我们的数据存放到Redis的时候,键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用JdkSerializationRedisSerializer,而StringRedisTemplate默认使用StringRedisSerializer。所有我们需要让用户类AyUser(/src/main/java/com.example.demo.model)实现序列化接口Serializable,具体代码如下:

/*** 描述:用户表* @Author 阿毅* @date   2017/10/8.*/
@Entity
@Table(name = "ay_user")
public class AyUser implements Serializable{//省略代码
}

7.3.2 项目启动缓存数据

在7.3.1节中,我们已经开发好AyUserListener监听器类和AyUser用户类,重新启动项目,这时候数据库表ay_user中的所有数据都会加载到Redis缓存中。在contextInitialized方法中打断点调试,出现如图7-9所示的图片,代码数据已经成功被加载到缓存中。 同时,我们也可以用Redis Client客户端软件来查看用户数据是否存放到缓存中。


图7-9 redis断点调试界面

7.3.3 更新缓存数据

项目启动加载所有用户数据到缓存之后,我们需要修改AyUserServiceImpl中的接口,比如
findById、save、delete等方法。因为如果在Redis缓存中查询不到数据,我们需要到数据库查询,如果能够在数据库中查询到数据,除了返回数据之外,还需要把数据更新到缓存中。这样下次再次查询数据时,就不需要到数据库中查询数据。这里主要对方法findById进行修改AyUserServiceImpl具体需要修改的代码如下:

//省略代码
@Service
public class AyUserServiceImpl implements AyUserService {@Resource(name = "ayUserRepository")private AyUserRepository ayUserRepository;@Resourceprivate RedisTemplate redisTemplate;private static final String ALL_USER = "ALL_USER_LIST";@Overridepublic 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  查询数据库中的数据AyUser ayUser = ayUserRepository.findOne(id);if(ayUser != null){//step.3 将数据插入到Redis缓存中redisTemplate.opsForList().leftPush(ALL_USER, ayUser);}return ayUser;}//省略}

对于save、delete等方法的修改,思路是一样的,这里就不一一重复累述,作为大家的任务自己实现。虽然引入Redis缓存用户数据可以提高访问性能,但是带来的代码复杂度也是可想而知的。所以在以后的工作钟,在性能和代码复杂度的权衡下,大家要根据具体的业务场景去加以选择,不可滥用缓存。这是要跟大家提醒的重要点。

7.3.4 测试

7.3.3节代码开发完成之后,我们在测试类MySpringBootApplicationTests下继续添加如下的
测试方法:

@Testpublic void testFindById(){Long redisUserSize = 0L;//查询id = 1 的数据,该数据存在于redis缓存中AyUser ayUser = ayUserService.findById("1");redisUserSize = redisTemplate.opsForList().size("ALL_USER_LIST");System.out.println("目前缓存中的用户数量为:" + redisUserSize);System.out.println("--->>> id: " + ayUser.getId() + " name:" + ayUser.getName());//查询id = 2 的数据,该数据存在于redis缓存中AyUser ayUser1 = ayUserService.findById("2");redisUserSize = redisTemplate.opsForList().size("ALL_USER_LIST");System.out.println("目前缓存中的用户数量为:" + redisUserSize);System.out.println("--->>> id: " + ayUser1.getId() + " name:" + ayUser1.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条数据,具体如图7-10所示,会重新被添加到Redis缓存中。项目启动成功之后,我们往数据库表ay_user添加id为4的第四条数据,具体如图7-11所示。


图7-10 数据库钟存在3条数据 图7-11 插入id为4的数据

最后我们执行单元测试方法testFindById(),在Intellij IDEA的控制台中会打印如下的信息:

目前缓存中的用户数量为:3
--->>> id: 1 name:阿毅
目前缓存中的用户数量为:3
--->>> id: 2 name:阿兰
--->>> id: 4 name:test
目前缓存中的用户数量为:4

读书感悟

来自《环保的暴力》

  • 唯有保护人类自由发展的权力,唯有人类财富的增长和未来的技术进步,才是解决环境问题乃至一切人类问题的根本途径。
  • 地球气候的变化是一个自然过程,主要是由于地球绕太阳轨道的变化所引起的,人类对气候的影响程度很小很小。

经典故事

1858年,瑞典的一个富豪人家生下了一个女儿。然而不久,孩子染患了一种无法解释的瘫痪症,丧失了走路的能力。一次,女孩和家人一起乘船旅行。船长的太太给孩子讲,船长有一只天堂鸟,她被这只鸟的描述迷住了,极想亲自看一看。于是保姆把孩子留在甲板上,自己去找船长。孩子耐不住性子等待,她要求船上的服务生立即带她去看天堂鸟。那服务生并不知道她的腿不能走路,而只顾带着她一道去看那只美丽的小鸟。奇迹发生了,孩子因为过度地渴望,竟忘我地拉住服务生的手,慢慢地走了起来。从此,孩子的病便痊愈了。女孩子长大后,又忘我地投入到文学创作中,最后成为第一位荣获诺贝尔文学奖的女性,也就是茜尔玛·拉格萝芙。
【忘我是走向成功的一条捷径,只有在这种环境中,人才会超越自身的束缚,释放出最大的能量。】


大神文章


其他

如果有带给你一丝丝小快乐,就让快乐继续传递下去,欢迎鼓励,点赞、顶、欢迎留下宝贵的意见、多谢支持!

第7章 集成Redis缓存相关推荐

  1. Spring Boot集成Redis缓存之模拟高并发场景处理

    前言 同样我们以上一篇文章为例子,搭建好环境之后,我欧美可以模拟高并发场景下,我们的缓存效率怎么样,到底能不能解决我们实际项目中的缓存问题.也就是如何解决缓存穿透? Spring Boot集成Redi ...

  2. Spring Boot 集成 Redis 缓存

    Spring Boot 集成 Redis 缓存 在此章,我们将 SpringBoot 集成 Redis 缓存,Redis是一个开源的,基于内存的数据结构存储,可以用作数据库.缓存和消息代理,在本章仅讲 ...

  3. springboot mybatis ehcache_SpringBoot入门建站全系列(十四)集成Redis缓存

    SpringBoot入门建站全系列(十四)集成Redis缓存 一.概述 本地缓存,就是使用应用内使用本地内存将数据暂缓存储,一般数据库的查询如果不怎么改动,可以用本地缓存暂存. 远程缓存,比如redi ...

  4. SpringBoot集成Redis缓存

    SpringBoot集成Redis缓存 前言 本系列文章将简单的学习SpringCloud微服务相关知识,其实也是因为时间的原因,一直拖到现在,遂打算趁着假期,决定记录下来. 从天气预报微服务系统的单 ...

  5. 若依框架集成redis缓存

    本文针对若依单体项目,主要介绍如何集成redis缓存. 目录 1.添加依赖 2.修改配置 3.增加配置 4.增加工具类

  6. Spring Boot集成Redis缓存之RedisTemplate的方式

    前言 Spring Boot 集成Redis,将自动配置 RedisTemplate,在需要使用的类中注入RedisTemplate的bean即可使用 @Autowired private Redis ...

  7. 搞懂分布式技术14:Spring Boot使用注解集成Redis缓存

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/a724888/article/details/80785403 为了提高性能,减少数据库的压力,使用 ...

  8. redis 依赖_springboot|springboot集成redis缓存

    javaDEMO 本网站记录了最全的各种JavaDEMO ,保证下载,复制就是可用的,包括基础的, 集合的, spring的, Mybatis的等等各种,助力你从菜鸟到大牛,记得收藏哦~~https: ...

  9. Spring Boot集成Redis缓存之注解方式

    首先还是加入依赖Jar pom.xml中加入依赖 <!-- 加载spring boot redis 包 --><dependency><groupId>org.sp ...

最新文章

  1. makefile讲义(1)——makefile基础(概述)
  2. “service httpd does not support chkconfig” 問題
  3. Store Kit Guide(In App Purchase)翻译
  4. 0212互联网新闻 | 华为将发布5G折叠屏手机;谷歌在小范围内推出AR实景导航
  5. Linux下C语言串口应用编程,Linux下串口C语言编程
  6. leetcode面试题 08.03. 魔术索引(二分)
  7. 带通滤波器作用和用途_常见低通、高通、带通三种滤波器的工作原理
  8. P3317 [SDOI2014]重建
  9. validated 验证数组_SpringBoot整合表单验证注解@Validated,以及分组验证
  10. RegExp()方法参数含义和使用方法
  11. delphi 断点调试android,Delphi 2010远程调试 - 无法使断点工作
  12. Modbus RTU CRC校验码计算方法
  13. shm 共享内存 android,共享内存
  14. MATLAB画函数图像
  15. 江苏省高等数学竞赛经验分享
  16. 后端使用SpringBoot和Jwt工具与Redis数据库+前端Vue Element Admin实现用户携带token的登录功能案例
  17. 字节跳动面试:京东面试真题解析,薪资翻倍
  18. 加薪不如发奖金? 穆穆-movno1
  19. Java程序员工作一年之后的感想
  20. 银河麒麟踩坑笔记——tty、单用户模式

热门文章

  1. leetcode-189. 轮转数组
  2. 机器学习-时间序列(一):日期和时间处理
  3. 自己的电脑该怎么当web服务器
  4. 三大运营商手机号段分配情况
  5. H3CNE-DHCP(动态主机配置协议)
  6. FPGA-Verilog多功能数字时钟
  7. 双非大厂测试员亲述:对测试员来说,学历重要吗?
  8. 扫描仪扫描文件处理-富士通ix500参数
  9. wifi 概率性自动断线(IpReachabilityMonitor)
  10. 华为“引商”,VR“刻羽”,共觅知音人