redis 是一款开源的 Key-Value 数据库,运行在内存中,由 ANSI C 编写。企业开发通常采用 Redis 来实现缓存。同类的产品还有 memcache 、memcached 、MongoDB 等。
Redis支持丰富的数据结构,常用的有string、list、hash、set、sortset这几种。学习这些数据结构是使用Redis的基础!
首先还是得声明一下,Redis的存储是以key-value的形式的。Redis中的key一定是字符串,value可以是string、list、hash、set、sortset这几种常用的。
一,Redis的下载和使用
目前官网只提供了linux版本的下载,我们想要使用windows版本的,只能在github上下载。
官网下载地址:http://redis.io/download
windows版本的Redis在github下载地址:https://github.com/MSOpenTech/redis/tags
为了大家使用方便,博主在文章末的示例项目提供了redis的windows版本,里面中win32位和win64位,供大家使用。
将下载的redis解压到指定的目录
主要有三个核心文件:
redis.windows.conf 配置文件,里面是关于redis的一些配置,一般情况下,使用默认即可。
redis-cli.exe 启动客户端执行文件。
redis-server.exe启动服务端执行文件
点击redis-server.exe启动redis服务
二,把Redis设置成windows下的服务
上面这种方式,虽然启动了Redis服务,但是只要一关闭cmd窗口,redis就会消失。所以要把redis设置成windows下的服务。
设置服务命令
redis-server --service-install redis.windows.conf --loglevel verbose
打开cmd,进入到redis的安装目录,执行上面的命令
我们win + R 键 打开运行窗口,输入services.msc 查看windows服务
选中Redis服务,右键属性
点击服务状态下的启动按钮这个服务就进行了开启。如果你想让这个服务在电脑开机的时候就启动,在这个服务启动之后,启动类型保持默认自动就可以了,如果不想电脑开机时就启动这个服务,可以设置启动类型为手动。博主在这里选择手动启动类型,在需要这个服务时,再进行启动,给电脑减轻负担,嘿嘿,有没有很机智!
这个服务被设置为windows服务之后,还有一种方便的启动与停止的方式。
以管理员身份打开cmd窗口,输入 net start 服务名 即可启动windows服务
输入net stop 服务名 ,停止windows服务
这样方式有没有看起来逼格更高一点呢,小小嘚瑟一下?
注意:
1.一定要以管理员的身份运行cmd窗口
2.服务名对应windows服务列表中的服务名称
三, redis-cli.exe 启动客户端
言归正传,我们下面介绍使用redis-cli.exe客户端可执行文件启动redis客户端来操作Redis
点击redis安装目录下的redis-cli.exe启动客户端(服务端要保存开启状态)
redis的常用操作命令:
查看所有的key:keys*
设置值: set key的名称 value值
获取指定key的值: get key的名称
四,Jedis 使用和图形界面工具
Jedis 是 Redis 官方推出的一款面向 Java 的客户端,提供了很多接口供 Java 语言调用。可以在 Redis 官网下载,当然还有一些开源爱好者提供的客户端,如 Jredis、SRP 等等,推荐使用 Jedis。
Jedis网址: https://github.com/xetorthio/jedis
创建一个maven项目
主要引入的依赖:
Jedis : redis的java客户端
Junit :方便进行代码测试
引入的插件:
maven-compiler-plugin : 由于maven项目默认的编译插件版本过低,需要这个编译插件来设置编译的版本
<dependencies>
<!-- Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
在引入编译插件之后,项目会报错,需要选中项目---->右键---->Maven---->Update Project 来更新项目
项目的编译版本修改成功,变更为1.7
准备工作就绪,接下来编写redis java客户端代码,进行测试
@Test
public void redisTest() {
Jedis jedis = new Jedis("localhost"); //localhost 表示连接的是本地的Redis服务端
jedis.set("foo", "苹果");
String value = jedis.get("foo");
System.out.println(value);
}
控制台输出
说明连接redis服务端连接成功,可以进行简单的存值和取值
我们可以打开redis-cli.exe客户端查看刚才设置的key和value
当我们存取中文字符时,用redis-cli.exe客户端查看发现对中文字符进行了转码,查看不很方便,这时,我们可以安装redis 安装图形化界面客户端来进行查看
这个安装程序,在文章末的示例项目中提供。安装步骤很简单,不再演示。
安装成功之后,按照下面操作即可
点击创建的连接,里面有16个db,默认使用的是db0
TTL 是 redis 的 key 有效时间,显示-1 ,没有设置 key 的有效期
一般通过java程序设置key的有效时间,不会使用图形化界面来进行设置
设置key的有效周期
使用图形化界面查看
如果我们要设置key的有效时间为一天,那么需要设置 60 * 60 * 24秒,这样来换算,显得不是很方便。当然,Jedis在很多方面的操作都是比较偏向底层的,使用起来不是很方便,而是在其上在封装一层,作为业务的使用。通常在开发中,使用Spring Data Redis来操作Redis。
五,Spring Data Redis 使用
Spring-data-redis 是 spring 大家族的一部分,提供了在 srping 应用中通过简单的配置访问 redis 服务,对 reids 底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate 提供了 redis 各种操作、异常处理及序列化,支持发布订阅,并对 spring 3.1 cache 进行了实现。
spring-data-redis 针对 jedis提供了如下功能:
1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2.针对jedis客户端的大量api进行了归类封装,把同一类型的操作封装成了Operation接口.支持redis中的五种数据类型的操作.
3.针对数据的"序列化与反序列化",提供了多种可以选择的策略(RedisSerializer)
JdkSerializationRedisSerializer:当需要存储java对象时使用.
StringRedisSerializer:当需要存储string类型的字符串时使用.
JacksonJsonRedisSerializer:将对象序列化成json的格式存储在redis中,需要jackson-json工具的支持
redisTemplate有两个方法经常用到,一个是opsForXXX一个是boundXXXOps,XXX是value的类型
opsForXXX和boundXXXOps的区别
前者获取到一个Opercation,但是没有指定操作的key,可以在一个连接(事务)内操作多个key以及对应的value;后者会获取到一个指定了key的operation,在一个连接内只操作这个key对应的value.
在实际开发过程中,选择其中任意一种方式都可以。不过在示例项目中,这两种方式都进行演示,大家根据喜好进行选择。
==========================================================
在项目的pom.xml文件中引入的依赖:
spring-data-redis:对 reids 底层开发包(Jedis, JRedis, and RJC)进行了高度封装,提供了一个高度封装的“RedisTemplate”类来操作redis
spring-test:加载spring的配置文件,方便测试
<dependencies>
<!-- Jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--spring-data-redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.3.RELEASE</version>
</dependency>
<!--spring整合juint测试 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
</dependencies>
spring的配置文件applicationContext-cache.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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:cache="http://www.springframework.org/schema/cache"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- Jedis数据库连接池 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="300" />
<property name="maxWaitMillis" value="3000" />
<!-- 保证获得的每一个Jedis实例都是可用的 -->
<property name="testOnBorrow" value="true" />
</bean>
<!-- redis连接工厂 跟配置数据库连接池类似,需要配置JedisConnectionFactory来通过服务器或者连接池的方式获取redis服务器的连接 -->
<bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="localhost" p:port="6379" p:pool-config-ref="poolConfig"
p:database="0" />
<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
<!-- redis模板配置 spring-data-redis提供了一个基础的泛型RedisTemplate封装了基础的crud操作-->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<!-- 序列化配置 可选配置-->
<property name="defaultSerializer" ref="stringRedisSerializer"/>
<property name="keySerializer" ref="stringRedisSerializer"/>
<property name="valueSerializer" ref="stringRedisSerializer"/>
</bean>
</beans>
编写代码演示opsForXXX的用法
方法一:opsForValue() 简单 K-V 操作
/**
* 简单key-value类型操作
*/
@Test
public void opsForValue() {
//设置key和value 并设置key的有效时间
redisTemplate.opsForValue().set("opsForValue", "小鬼",30,TimeUnit.SECONDS);
String value = (String) redisTemplate.opsForValue().get("opsForValue");
System.out.println(value);
}
/**
* 简单key-value类型删除操作
*/
@Test
public void delOpsForValue() {
redisTemplate.delete("opsForValue");
}
使用redis客户端图形化界面查看
方法二:opsForHash() 针对 map 类型的数据操作
这次不再向先前那样,存放字符串,尝试存放的数据是一个装着User对象的List集合
/**
* 针对 map 类型的数据操作
*/
@Test
public void opsForHash() {
List<User> list = new ArrayList<>();
User u1 = new User();
u1.setId(1);
u1.setAge(1);
u1.setUsername("小张");
User u2 = new User();
u2.setId(2);
u2.setAge(2);
u2.setUsername("小王");
list.add(u1);
list.add(u2);
//向redis中存入一个list集合,list集合中存放的是user对象
//第一个参数 属于大key 对应的值value是一个map 第二个参数是map的key 第三个参数是map的value
redisTemplate.opsForHash().put("opsForHash", "mapKey",list);
}
执行单元测试,出现了错误
java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String
大概就是说类转换异常,不能把ArrayList类转成String类
出现的原因:
解决方式有两种:
方式一:
1.修改属性keySerializer为hashKeySerializer 2.修改属性valueSerializer为hashValueSerializer 对应的ref="jdkSerializationRedisSerializer" <bean id="stringRedisSerializer"
class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
<bean id="jdkSerializationRedisSerializer"
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
<!-- redis模板配置 spring-data-redis提供了一个基础的泛型RedisTemplate封装了基础的crud操作-->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
<!-- 序列化配置 可选配置-->
<property name="defaultSerializer" ref="stringRedisSerializer"/>
<property name="hashKeySerializer" ref="stringRedisSerializer"/>
<property name="hashValueSerializer" ref="jdkSerializationRedisSerializer"/>
</bean>
2.,注释掉序列化配置,使用默认的即可,推荐使用第二种。可以减少配置的同时,麻烦也少了
第二种实现的原理:
通过查看RedisTemplate
这个类的源码,发现由于defaultSerializer
的序列化方式被初始化为JdkSerializationRedisSerializer
,再通把defaultSerializer
的值赋值给keySerializer,valueSerializer,hashKeySerializer,hashValueSerializer
,所以他们的值都为JdkSerializationRedisSerializer
。当向redis中存储不是String字符串也是OK的。
修改完配置文件,进行代码测试
/**
* 针对 map 类型的数据操作
*/
@Test
public void opsForHash() {
List<User> list = new ArrayList<>();
User u1 = new User();
u1.setId(1);
u1.setAge(1);
u1.setUsername("小张");
User u2 = new User();
u2.setId(2);
u2.setAge(2);
u2.setUsername("小王");
list.add(u1);
list.add(u2);
//向redis中存入一个list集合,list集合中存放的是user对象
//第一个参数 属于大key 对应的值value是一个map 第二个参数是map的key 第三个参数是map的value
redisTemplate.opsForHash().put("opsForHash", "mapKey",list);
redisTemplate.opsForHash().put("opsForHash", "mapKey2",list);
redisTemplate.opsForHash().put("opsForHash", "mapKey3",list);
//获取所有的小key
Set keys = redisTemplate.opsForHash().keys("opsForHash");
System.out.println("获取所有的小key:"+keys);
//获取所有的value
list = redisTemplate.opsForHash().values("opsForHash");
System.out.println("获取所有的value: "+list);
//获取某一个小key的value
list =(List<User>) redisTemplate.opsForHash().get("opsForHash", "mapKey");
System.out.println("获取某一个小key的value: "+list);
}
控制台成功输出
删除大key中的某一个小key 和 删除整个大key
/**
* 针对 map 数据删除操作
*/
@Test
public void delOpsForHash() {
//删除大key中的某一个map
redisTemplate.opsForHash().delete("opsForHash", "mapKey");
//删除大key
redisTemplate.delete("opsForHash");
}
===========================================================
剩下的三种方式使用大致相同,不做演示
opsForSet() set 类型数据操作
opsForList() 针对 list 类型的数据操作
opsForZSet() zset 类型数据操作
编写代码演示BoundXXXOpsTest的用法
方法一:boundValueOps() 简单 K-V 操作
/**
* 简单key-value类型操作
*/
@Test
public void boundValueOps() {
//设置key和value 并设置key的有效时间
redisTemplate.boundValueOps("boundValueOps").set("小鬼",30,TimeUnit.SECONDS);
String value = (String) redisTemplate.opsForValue().get("boundValueOps");
System.out.println(value);
}
/**
* 简单key-value类型删除操作
*/
@Test
public void delBoundValueOps() {
redisTemplate.delete("boundValueOps");
}
方法二:boundHashOps() 针对 map 类型的数据操作
/**
* 针对 map 类型的数据操作
*/
@Test
public void boundHashOps() {
List<User> list = new ArrayList<>();
User u1 = new User();
u1.setId(1);
u1.setAge(1);
u1.setUsername("小张");
User u2 = new User();
u2.setId(2);
u2.setAge(2);
u2.setUsername("小王");
list.add(u1);
list.add(u2);
//向redis中存入一个list集合,list集合中存放的是user对象
//第一个参数 属于大key 对应的值value是一个map 第二个参数是map的key 第三个参数是map的value
redisTemplate.boundHashOps("boundHashOps").put("key1", list);
redisTemplate.boundHashOps("boundHashOps").put("key2", list);
redisTemplate.boundHashOps("boundHashOps").put("key3", list);
//获取所有的小key
Set keys = redisTemplate.boundHashOps("boundHashOps").keys();
System.out.println("获取所有的小key:"+keys);
//获取所有的value
list = redisTemplate.boundHashOps("boundHashOps").values();
System.out.println("获取所有的value: "+list);
//获取某一个小key的value
list =(List<User>) redisTemplate.boundHashOps("boundHashOps").get("key1");
System.out.println("获取某一个小key的value: "+list);
}
/**
* 针对 map 数据删除操作
*/
@Test
public void delBoundHashOps() {
//删除大key中的某一个map
redisTemplate.boundHashOps("boundHashOps").delete("key1");
//删除大key
redisTemplate.delete("opsForHash");
}
剩下的三种方式使用大致相同,不做演示
boundSetOps() set 类型数据操作
boundListOps() 针对 list 类型的数据操作
boundZSetOps() zset 类型数据操作
==================================================================
以上就是有关Spring-data-redis对Redis的常用操作,后续会补充Redis搭建集群的相关知识。
最后分享示例项目在码云的地址:https://gitee.com/xiaoguixiaogege/springdataredis