文档章节

Redis及Spring-Data-Redis入门学习

T
 TyCoding
发布于 2018/09/25 19:54
字数 2251
阅读 43
收藏 0

继上一篇Solr和Spring Data Solr学习,我们思考一个问题,使用Solr的目的是什么?肯定是为了加快服务器的相应速度。因为即使不适用Solr,通过请求数据库我们一样能完成搜索功能,但是这样会给服务器造成很大的压力。

而Solr仅仅是在搜索功能中用到了,但是大量请求的数据不仅仅出现在搜索中,比如用户的登录信息,虽然数据量很小,但是整个项目每刷新一次页面都要请求一次用户登录的Token信息,也会拖慢服务器的响应速度。我们通常有两中解决方式:1.数据缓存;2.网页静态化。

其实我们在Shiro实现用户-角色-权限管理系统中已经用到了缓存技术,今天我们了解一下Redis缓存技术。

项目开源地址: Github

安装Redis

Redis是一款开源的Key-Value数据库。首先我们要去 官网 下载Redis,由于笔者使用的是MacOS系统,和Windows系统有所不同。

安装过程不再叙述,这里提供两个教程:

<br/>

启动Redis

redis-server 
redis-server &

建议使用第二个命令,用第二个命令启动了redis server后能继续输入命令,使用第一个命令则不行。

如果终端中显示如下logo表示redis启动成功:

<br/>

操纵Redis

上面仅仅是启动了Redis Server,但Redis是一种Key-Value型数据库,也包含了一些查询数据库的命令,操作redis命令的入口就是: redis/bin/redis-cli

./bin/redis-cli

redis-cli

  1. 查看当前(db0)数据库中所有的key值: keys *
  2. 清空当前数据库中所有的数据: flushall

更多的Redis命令可以参看:redis中文文档

<br/>

Spring Data Redis

之前学习Solr的时候用到了Spring Data Solr,现在学习Redis,Spring提供了Spring Data Redis用来实现通过配置文件的方式访问redis服务。Spring Data Redis对Redis底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化。

Jedis

Jedis是Redis官方推出的一款面向Java的客户端,提供了很多借口供Java语言调用。

Spring Data Redis针对Jedis提供了如下功能:

  • 1.连接池自动管理,提供了一个高度封住的RedisTemplate类。
  • 2.针对jedis客户端中大量api进行归类封装,将同一类型操作封装为operation接口: ValueOperations: 简单的K-V操作 SetOperations: set类型数据操作 ZSetOperations: zset类型数据操作 HashOperations: 针对Map类型的数据操作 ListOperations: 针对List类型的数据操作

准备

导入依赖

<dependency> 
		  <groupId>redis.clients</groupId> 
		  <artifactId>jedis</artifactId> 
		  <version>2.8.1</version> 
</dependency> 
<dependency> 
		  <groupId>org.springframework.data</groupId> 
		  <artifactId>spring-data-redis</artifactId> 
		  <version>1.7.2.RELEASE</version> 
</dependency>	

创建redis-config.properties

redis.host=127.0.0.1 
redis.port=6379 
redis.pass= 
redis.database=0 
redis.maxIdle=300 
redis.maxWait=3000 
redis.testOnBorrow=true

解释

  1. redis.host是安装redis server的客户端IP地址,如果安装在本机上就是127.0.0.1,如果安装在服务器上请修改为服务器的IP地址。
  2. redis.port是redis server的默认端口,你安装了redis,就默认使用这个端口号。
  3. redis.pass是访问redis server的密码,一般我们不设置。
  4. redis.database=0代表使用的是redis默认提供的db0这个数据库。
  5. redis-maxIdle是redis server的最大空闲数。
  6. redis-maxWait是连接redis时的最大等待毫秒数。
  7. redis-testOnBorrow在提取一个redis实例时,是否提前进行验证操作;如果为true,则得到的jedis实例均是可用的。

创建spring-redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder location="classpath:other/*.properties"/>
    <!-- redis 相关配置 -->
    <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大空闲数 -->
        <property name="maxIdle" value="${redis.maxIdle}"/>
        <!-- 连接时最大的等待时间(毫秒) -->
        <property name="maxWaitMillis" value="${redis.maxWait}"/>
        <!-- 在提取一个jedis实例时,是否提前进行验证操作;如果为true,则得到的jedis实例均是可用的 -->
        <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
    </bean>
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="${redis.host}"/>
        <property name="port" value="${redis.port}"/>
        <property name="password" value="${redis.pass}"/>
        <property name="poolConfig" ref="poolConfig"/>
    </bean>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory"/>
    </bean>
</bean>

实例

本实例源码:Github

首先加载配置文件spring-redis.xml,注入RedisTemplate模板类:

@Autowired
private RedisTemplate redisTemplate;

值类型

RedisTemplate提供的很多操作redis数据库的方法都是boundxxOps这种。

添加

@Test
public void setValue(){
    redisTemplate.boundValueOps("name").set("tycoding");
}

如果配置都正常的情况下,运行此方法就能向db0数据库中添加一条key为name的记录;那么我们在redis命令行中查看所有的key:

奇怪,我添加的key明明是name,为什么查出来的确实一堆乱码值呢?我们再使用redis命令行单独添加一条记录:

set testK testV

此时我们又发现,使用redis原生命令添加的数据是不会乱码的;那么就肯定是Spring Data Redis的原因了。经查询是因为redisTemplate模板类在操作redis序列化的原因,我们要手动配置序列化方式为:StringRedisSerializer

修改之前创建的spring-redis.xml配置文件:

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory"/>

    <!-- 序列化策略 推荐使用StringRedisSerializer -->
    <property name="keySerializer">
        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    </property>
    <property name="valueSerializer">
        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    </property>
    <property name="hashKeySerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    </property>
    <property name="hashValueSerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    </property>
</bean>

再次添加数据

查询

@Test
public void getValue(){
    Object name = redisTemplate.boundValueOps("name").get();
    System.out.println(name);
}

删除

@Test
public void deleteValue(){
    redisTemplate.delete("name");
}

Set类型

添加

@Test
public void setValueBySet(){
    redisTemplate.boundSetOps("nameset").add("tycoding");
}

查询

@Test
public void getValueBySet(){
    Set nameset = redisTemplate.boundSetOps("nameset").members();
    System.out.println(nameset);
}

删除Set中某一个值

@Test
public void deleteValueBySet(){
    redisTemplate.boundSetOps("nameset").remove("涂陌");
}

删除整个Set

@Test
public void deleteAllValueByset(){
    redisTemplate.delete("nameset");
}

List类型

右压栈

右压栈,后添加的对象排在后边

@Test
public void setRightValueByList(){
  redisTemplate.boundListOps("namelist").rightPush("tycoding");
  redisTemplate.boundListOps("namelist").rightPush("涂陌");
}

显示右压栈集合

@Test
public void getRightValueByListI(){
    List namelist = redisTemplate.boundListOps("namelist").range(0, 10);
    System.out.println(namelist);
}

左压栈

左压栈,后添加的对象排在前面

    @Test
    public void setLeftValueByList(){
        redisTemplate.boundListOps("namelist2").leftPush("tycoding");
        redisTemplate.boundListOps("namelist2").leftPush("涂陌");
    }

显示左压栈的集合:

    @Test
    public void getLeftValueByList(){
        List name2 = redisTemplate.boundListOps("namelist2").range(0, 10);
        System.out.println(name2);
    }

根据索引查询集合中的元素

    @Test
    public void searchByIndex(){
        Object namelist = redisTemplate.boundListOps("namelist").index(1);
        System.out.println(namelist);
    }

Hash类型

添加

    @Test
    public void setValueByHash(){
        redisTemplate.boundHashOps("namehash").put("a","tycoding");
    }

提取所有的KEY

    @Test
    public void getKeysByHash(){
        Set namehash = redisTemplate.boundHashOps("namehash").keys();
        System.out.println(namehash);
    }

提取所有的VALUE

    @Test
    public void getValuesByHash(){
        List namehash = redisTemplate.boundHashOps("namehash").values();
        System.out.println(namehash);
    }

根据KEY取值

    @Test
    public void getValueByHash(){
        Object o = redisTemplate.boundHashOps("namehash").get("a");
        System.out.println(o);
    }

根据KEY移除值

    @Test
    public void deleteValueByHash(){
        redisTemplate.boundHashOps("namehash").delete("a");
    }

<br/>

测试

上面说了一大堆,没有实际的测试,着实不清楚Redis究竟效果如何,是不是真的提高了访问速度?

下面我们以查询数据库所有值的功能来看一下使用Redis缓存和未使用缓存直接查询数据库所用时间。

本例源码地址:Github

未使用Redis缓存,直接请求数据库

public List<Goods> findAll() {
        return goodsMapper.findAll();
}

使用了Redis缓存

首先通过boundHashOps获取Redis数据库中是否存在KEY为all的数据,有的话就返回;没有的话就查询数据库并将查询到的数据添加到Redis数据库中,且KEY为all

public List<Goods> findAll() {
    List<Goods> contentList = (List<Goods>) redisTemplate.boundHashOps("goods").get("all");
    if (contentList == null) {
        //说明缓存中没有数据
        System.out.println("从数据库中读取数据放入redis...");
        contentList = goodsMapper.findAll();
        redisTemplate.boundHashOps("goods").put("all", contentList); //存入redis中
    } else {
        System.out.println("从缓存中读取数据...");
    }

//        return goodsMapper.findAll();
    return contentList;
}

TestTime.java

@Test
public void run1() {
    Long startTime = System.currentTimeMillis(); //开始时间
    goodsMapper.findAll();
    Long endTime = System.currentTimeMillis(); //结束时间
    System.out.println("查询数据库--共耗时:" + (endTime - startTime) + "毫秒"); //1007毫秒
}

@Test
public void run2() {
    Long startTime = System.currentTimeMillis(); //开始时间
    goodsService.findAll();
    Long endTime = System.currentTimeMillis(); //结束时间
    System.out.println("从redis中读取所有数据,共耗时:" + (endTime - startTime) + "毫秒");
}

在测试类中调用Service层的这两个方法,得到的结果如下:

查询数据库--共耗时:1047毫秒

从redis中读取所有数据,共耗时:197毫秒

<br/>

交流

如果大家有兴趣,欢迎大家加入我的Java交流技术群:671017003 ,一起交流学习Java技术。博主目前一直在自学JAVA中,技术有限,如果可以,会尽力给大家提供一些帮助,或是一些学习方法,当然群里的大佬都会积极给新手答疑的。所以,别犹豫,快来加入我们吧!

<br/>

联系

If you have some questions after you see this article, you can contact me or you can find some info by clicking these links.

© 著作权归作者所有

T
粉丝 20
博文 23
码字总数 68904
作品 0
安阳
私信 提问
使用SSM+Solr优雅的实现电商项目中的搜索功能

在学习了Redis&Spring-Data-Redis入门和Solr&Spring-Data-Solr入门后,接下来就该是项目实战了。这次我们用Vue.JS和ElementUI写前端页面,优雅的整合SSM-Shiro-Redis-Solr框架。 手摸手教你优...

TyCoding
2018/09/25
0
0
springboot从入门到精通教程分享, 深度掌握Springboot实践技术教程

深度掌握Springboot实践技术教程,共22个课时,需要的可回复邮箱。 课程简介 day1 01springboot简介-曾经开发中的问题 02springboot解决的问题-优势以及弊端 03springboot环境准备 04spring...

小小倾听
2018/12/06
0
0
springboot cache redis 缓存

上一节学习spring的cache缓存,介绍了spring缓存的基础: https://my.oschina.net/silenceyawen/blog/1555996 现在学习使用redis实现缓存: 1. 指定provider可以使用配置: 2. redis在这里充...

yawnSilence
2017/10/26
0
0
Spring Cloud Data Flow 2.0.1 GA 发布

Spring Cloud Data Flow 2.0.1 GA 已发布,该版本的更新内容主要是 bug 修复和文档增强。 更新亮点如下: Skipper 服务器的 Kubernetes 部署配置使用 MySQL 作为默认数据库 删除无关的 Spri...

段段段落
03/20
0
0
聊聊spring-boot-starter-data-redis的配置变更

序 本文主要研究一下spring-boot-starter-data-redis的配置变更 配置变更 以前是spring-boot的1.4.x版本的(spring-data-redis为1.7.x版本),最近切到2.0.4.RELEASEB版本(spring-data-redis为...

go4it
2018/09/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

你需要知道的 5 个 Linux 新手会犯的失误

Linux 爱好者们分享了他们犯下的一些最大错误。 终身学习是明智的 —— 它可以让你的思维敏捷,让你在就业市场上更具竞争力。但是有些技能比其他技能更难学,尤其是那些小菜鸟错误,当你尝试...

xiangyunyan
2分钟前
0
0
来迟了,用Python助你叠猫猫,抢618大红包!

目录: 0 引言 1 环境 2 需求分析 3 前置准备 4 逛店铺流程回顾 5 代码全景展示 6 总结 0 引言 最近叠猫猫的活动可真是十分的火爆,每天小伙伴们为了合猫猫忙的可谓是如火如荼。为啥要叠猫猫...

上海小胖
9分钟前
0
0
FPGA 设备 USB Platform Cable USB

lsusbFuture Technology Devices International, Ltd FT232H Single HS USB-UART/FIFO IC

MtrS
今天
4
0
lua web快速开发指南(6) - Cache、DB介绍

"数据库"与"缓存"的基本概念 数据库与缓存是服务端开发人员的必学知识点. 数据库 "数据库"是一种信息记录、存取的虚拟标记地点的集合统称. 比如现实生活中, 我们经常会用到文件柜、书桌等等数...

水果糖的小铺子
今天
9
0
Oracle分页查询语句的写法

Oracle分页查询语句的写法 Oracle分页查询语句使我们最常用的语句之一,下面就为您介绍的Oracle分页查询语句的用法,Oracle分页查询语句基本上可以按本文给出的格式来进行套用。   Oracle分...

康师傅
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部