Redis篇(Java操作Redis)

目录

讲解一:简介

讲解二:Jedis

Github

一、创建项目、

二、添加依赖

三、配置文件

四、Java连接Redis

五、通过Redis连接池获取连接对象并操作服务器

六、封装JedisUtil对外提供连接对象获取方法

七、Java操作Redis五种数据类型

1. 连接与释放

2. Jedis操作string数据类型

3. Jedis操作hash类型

4. Jedis操作list类型

5. Jedis操作set类型

6. Jedis操作sortedset数据类型

八、层级目录+失效时间

九、获取所有key&事务&删除

十、Jedis操作byte数组

讲解三:SpringDataRedis

一、简介

二、创建项目

三、添加依赖

四、添加application.yml配置文件

五、Lettuce和Jedis的区别

六、测试环境测试环境是否搭建成功

七、SpringDataRedis序列化模板

1. 序列化问题

2. 序列化解决方案

3. 自定义序列化

4. StringRedisTemplate

八、SpringData操作Redis

1. 操作string数据类型

2. 操作hash数据类型

3. 操作list数据类型

4. 操作set数据类型

5. 操作sortedset数据类型

6. 获取所有key+设置key失效时间

获取所有key&删除

设置key的失效时间

7. 通用操作

九、SpringDataRedis整合哨兵

application.yml

Bean注解配置

十、知识小结


讲解一:简介

在Redis官网中提供了各种语言的客户端,

官网地址:Connect with Redis clients | Docs

操作Redis 的 Java 客户端很多,官方推荐的有三种:

  • Jedis
  • Lettuce
  • Redisson

标记为的就是推荐使用的java客户端,包括:

  • Jedis和Lettuce:这两个主要是提供了Redis命令对应的API,方便我们操作Redis,而Spring 对 Redis 客户

端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-

boot-starter-data-redis。

  • Redisson:是在Redis基础上实现了分布式的可伸缩的java数据结构,例如:Map、Queue等,而且支持跨

进程的同步机制:Lock、Semaphore等待,比较适合用来实现特殊的功能需求。

讲解二:Jedis

Github

Jedis 是 Redis 的 Java 版本的客户端实现。

Jedis的官网地址: https://github.com/redis/jedis

一、创建项目、

自己创建一个Maven项目

二、添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.4.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.xxxx</groupId><artifactId>redis-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>redis-demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><!--1.x 的版本默认采用的连接池技术是 Jedis,2.0 以上版本默认连接池是 Lettuce,如果采用 Jedis,需要排除 Lettuce 的依赖。--><exclusions><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><!-- jedis 依赖 --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency><!--web组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--test 组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies></project>

三、配置文件

spring:redis:# Redis服务器地址host: 192.168.10.100# Redis服务器端口port: 6379# Redis服务器密码password: root# 选择哪个库,默认0库database: 0# 连接超时时间timeout: 10000msjedis:pool:# 最大连接数,默认8max-active: 1024# 最大连接阻塞等待时间,单位毫秒,默认-1msmax-wait: 10000ms# 最大空闲连接,默认8max-idle: 200# 最小空闲连接,默认0min-idle: 5

四、Java连接Redis

/*** 连接Redis*/
@Test
public void initConn01() {// 创建jedis对象,连接redis服务Jedis jedis = new Jedis("192.168.10.100", 6379);// 设置认证密码jedis.auth("root");// 指定数据库 默认是0jedis.select(1);// 使用ping命令,测试连接是否成功String result = jedis.ping();System.out.println(result);// 返回PONG// 添加一条数据jedis.set("username", "zhangsan");// 获取一条数据String username = jedis.get("username");System.out.println(username);// 释放资源if (jedis != null)jedis.close();
}

Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,

因此我们推荐大家使用Jedis连接池代替Jedis的直连方式

package com.project.jedis.util;import redis.clients.jedis.*;public class JedisConnectionFactory {private static JedisPool jedisPool;static {// 配置连接池JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxTotal(8);poolConfig.setMaxIdle(8);poolConfig.setMinIdle(0);poolConfig.setMaxWaitMillis(1000);// 创建连接池对象,参数:连接池配置、服务端ip、服务端端口、超时时间、密码jedisPool = new JedisPool(poolConfig, "192.168.150.101", 6379, 1000, "123321");}public static Jedis getJedis(){return jedisPool.getResource();}
}

五、通过Redis连接池获取连接对象并操作服务器

/*** 通过Redis连接池获取连接对象*/
@Test
public void initConn02() {// 初始化redis客户端连接池JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "192.168.10.100", 6379, 10000, "root");// 从连接池获取连接Jedis jedis = jedisPool.getResource();// 指定数据库 默认是0jedis.select(2);// 使用ping命令,测试连接是否成功String result = jedis.ping();System.out.println(result);// 返回PONG// 添加一条数据jedis.set("username", "zhangsan");// 获取一条数据String username = jedis.get("username");System.out.println(username);// 释放资源if (jedis != null)jedis.close();
}

六、封装JedisUtil对外提供连接对象获取方法

@Configuration
public class RedisConfig {//服务器地址@Value("${spring.redis.host}")private String host;//端口@Value("${spring.redis.port}")private int port;//密码@Value("${spring.redis.password}")private String password;//超时时间@Value("${spring.redis.timeout}")private String timeout;//最大连接数@Value("${spring.redis.jedis.pool.max-active}")private int maxTotal;//最大连接阻塞等待时间@Value("${spring.redis.jedis.pool.max-wait}")private String maxWaitMillis;//最大空闲连接@Value("${spring.redis.jedis.pool.max-idle}")private int maxIdle;//最小空闲连接@Value("${spring.redis.jedis.pool.min-idle}")private int minIdle;@Beanpublic JedisPool redisPoolFactory(){JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();//注意值的转变jedisPoolConfig.setMaxWaitMillis(Long.parseLong(maxWaitMillis.substring(0,maxWaitMillis.length()-2)));//注意属性名jedisPoolConfig.setMaxTotal(maxTotal);jedisPoolConfig.setMaxIdle(maxIdle);jedisPoolConfig.setMinIdle(minIdle);JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, Integer.parseInt(timeout.substring(0,timeout.length() - 2)), password);return jedisPool;}
}

七、Java操作Redis五种数据类型

1. 连接与释放

@Autowired
private JedisPool jedisPool;private Jedis jedis = null;//初始化jedis对象实例
@Before
public void initConn(){jedis = jedisPool.getResource();
}//释放资源
@After
public void closeConn(){if (jedis!=null){jedis.close();}
}

2. Jedis操作string数据类型

// 1.操作String
@Test
public void testString() {// 添加一条数据jedis.set("username", "zhangsan");jedis.set("age", "18");// 添加多条数据 参数奇数为key 参数偶数为valuejedis.mset("address", "bj", "sex", "1");// 获取一条数据String username = jedis.get("username");System.out.println(username);// 获取多条数据List<String> list = jedis.mget("username", "age", "address", "sex");for (String str : list) {System.out.println(str);}// 删除//jedis.del("username");}

3. Jedis操作hash类型

// 2.操作Hash
@Test
public void testHash() {/** 添加一条数据*     参数一:redis的key*     参数二:hash的key*     参数三:hash的value*/jedis.hset("userInfo", "name", "lisi");// 添加多条数据Map<String, String> map = new HashMap<>();map.put("age", "20");map.put("sex", "1");jedis.hmset("userInfo", map);// 获取一条数据String name = jedis.hget("userInfo", "name");System.out.println(name);// 获取多条数据List<String> list = jedis.hmget("userInfo", "age", "sex");for (String str : list) {System.out.println(str);}// 获取Hash类型所有的数据Map<String, String> userMap = jedis.hgetAll("userInfo");for (Entry<String, String> userInfo : userMap.entrySet()) {System.out.println(userInfo.getKey() + "--" + userInfo.getValue());}// 删除 用于删除hash类型数据//jedis.hdel("userInfo", "name");
}

4. Jedis操作list类型

 // 3.操作list@Testpublic void testList() {// 左添加(上)// jedis.lpush("students", "Wang Wu", "Li Si");// 右添加(下)//jedis.rpush("students", "Zhao Liu");// 获取start起始下标 end结束下标 包含关系List<String> students = jedis.lrange("students", 0, 2);for (String stu : students) {System.out.println(stu);}// 获取总条数Long total = jedis.llen("students");System.out.println("总条数:" + total);// 删除单条 删除列表中第一次出现的Li Si// jedis.lrem("students", 1, "Li Si");// 删除多条// jedis.del("students");}

5. Jedis操作set类型

/*** 操作set*/
@Test
public void testSet(){//添加数据jedis.sadd("letters","aaa","bbb","ccc","ddd","eee");//获取数据Set<String> set = jedis.smembers("letters");set.forEach(System.out::println);//获取总条数Long total = jedis.scard("letters");System.out.println(total);//删除数据jedis.srem("letters","aaa","bbb");
}

6. Jedis操作sortedset数据类型

/*** 操作sorted set*/
@Test
public void testSortedSet(){//添加数据Map<String,Double> map = new HashMap<>();map.put("zhangsan",7D);map.put("lisi",3D);map.put("wangwu",5D);map.put("zhaoliu",6D);map.put("tianqi",1D);jedis.zadd("score",map);/*** 获取数据*  第一个参数:redis的key*  第二个参数:起始下标*  第三个参数:结束下标*/Set<String> set = jedis.zrange("score", 0, 4);set.forEach(System.out::println);//获取总条数Long total = jedis.zcard("score");System.out.println(total);//删除数据jedis.zrem("score","zhangsan","wangwu");
}

八、层级目录+失效时间

Redis中以层级关系、目录形式存储数据

    /*** 层级目录形式存储数据*/@Testpublic void testDir(){jedis.set("cart:user01:item01","apple");System.out.println(jedis.get("cart:user01:item01"));}

设置key的失效时间

Redis 有四个不同的命令可以用于设置键的生存时间(键可以存在多久)或过期时间(键什么时候会被删除) :

EXPlRE :用于将键 key 的生存时间设置为 ttl 秒。

PEXPIRE :用于将键 key 的生存时间设置为 ttl 毫秒。

EXPIREAT < timestamp>:用于将键 key 的过期时间设置为 timestamp 所指定的秒数时间戳。

PEXPIREAT < timestamp >:用于将键 key 的过期时间设置为 timestamp 所指定的毫秒数时间戳。

TTL:获取的值为-1说明此 key 没有设置有效期,当值为-2时证明过了有效期。

    /*** key的失效时间*/@Testpublic void testExpire(){//给已经存在key设置失效时间// jedis.set("code","test");//设置失效时间,单位秒// jedis.expire("code",30);//设置失效时间,单位毫秒// jedis.pexpire("code",30000);//查看失效时间,单位秒。-1为不失效,-2为已失效// Long ttl = jedis.ttl("code");// System.out.println(ttl);//添加key的时候设置失效时间//设置失效时间,单位秒// jedis.setex("code",30,"test");//设置失效时间,单位毫秒// jedis.psetex("code",30000,"test");//查看失效时间,单位毫秒// Long pttl = jedis.pttl("code");// System.out.println(pttl);//nx,xx的用法SetParams setParams = new SetParams();//不存在的时候才能设置成功// setParams.nx();// 存在的时候才能设置成功setParams.xx();//设置失效时间,单位秒// setParams.ex(30);//查看失效时间,单位毫秒setParams.px(30000);jedis.set("code","test",setParams);}

九、获取所有key&事务&删除

    /*** 查询所有key*/@Testpublic void testAllKey(){//当前数据库key的数量Long size = jedis.dbSize();System.out.println(size);//查询当前数据库的所有keySet<String> set = jedis.keys("*");set.forEach(System.out::println);}/*** 事务*/@Testpublic void testMulti(){//开启事务Transaction tx = jedis.multi();tx.set("tel","10086");//提交事务tx.exec();//回滚事务// tx.discard();}

十、Jedis操作byte数组

操作byte

SerializeUtil.java

package com.xxxx.redisdemo.util;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;/*** 序列化工具类*/
public class SerializeUtil {/*** 将java对象转换为byte数组 序列化过程*/public static byte[] serialize(Object object) {ObjectOutputStream oos = null;ByteArrayOutputStream baos = null;try {// 序列化baos = new ByteArrayOutputStream();oos = new ObjectOutputStream(baos);oos.writeObject(object);byte[] bytes = baos.toByteArray();return bytes;} catch (Exception e) {e.printStackTrace();}return null;}/*** 将byte数组转换为java对象  反序列化*/public static Object unserialize(byte[] bytes) {if(bytes == null)return null;ByteArrayInputStream bais = null;try {// 反序列化bais = new ByteArrayInputStream(bytes);ObjectInputStream ois = new ObjectInputStream(bais);return ois.readObject();} catch (Exception e) {e.printStackTrace();}return null;}
}

User.java

package com.xxxx.redisdemo.pojo;import java.io.Serializable;public class User implements Serializable {private static final long serialVersionUID = 9148937431079191022L;private Integer id;private String username;private String password;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}

JedisTest.java

    /*** 操作byte数组*/@Testpublic void testByte(){User user = new User();user.setId(2);user.setUsername("zhangsan");user.setPassword("123456");//序列化为byte数组byte[] userKey = SerializeUtil.serialize("user:" + user.getId());byte[] userValue = SerializeUtil.serialize(user);//存入redisjedis.set(userKey,userValue);//取出数据byte[] bytes = jedis.get(userKey);//反序列化User user1 = (User) SerializeUtil.unserialize(bytes);System.out.println(user1);}

讲解三:SpringDataRedis

一、简介

Spring Data Redis是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,

对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。

官网地址:Spring Data Redis

maven坐标:

<dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-redis</artifactId><version>2.4.8</version></dependency>

SpringBoot已经提供了对SpringDataRedis的支持,使用非常简单。

Spring Boot提供了对应的Starter,maven坐标:

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

Spring Data Redis中提供了一个高度封装的类:RedisTemplate,

针对 Jedis 客户端中大量api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

  • ValueOperations:简单K-V操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作
  • HashOperations:针对hash类型的数据操作
  • ListOperations:针对list类型的数据操作

二、创建项目

自行创建一个 SpringBoot 项目

三、添加依赖

	<dependencies><!--spring-data-redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- commons-pool2 对象池依赖 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!--web组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--test组件--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies>

四、添加application.yml配置文件

spring:redis:  #redis配置# Redis服务器地址host: 192.168.136.160# Redis服务器端口port: 6379# Redis服务器密码password: root# Redis服务器0号数据库database: 0# 连接超时时间timeout: 10000mslettuce:pool:# 最大连接数,默认8max-active: 1024# 最大连接阻塞等待时间,单位毫秒,默认-1msmax-wait: 10000ms# 最大空闲连接,默认8max-idle: 200# 最小空闲连接,默认0min-idle: 5

五、Lettuce和Jedis的区别

Jedis 是一个优秀的基于 Java 语言的 Redis 客户端,但是,其不足也很明显:

Jedis 在实现上是直接连接 RedisServer,在多个线程间共享一个 Jedis 实例时是线程不安全的,

如果想要在多线程场景下使用 Jedis ,需要使用连接池,每个线程都使用自己的 Jedis 实例,

当连接数量增多时,会消耗较多的物理资源。

Lettuce 则完全克服了其线程不安全的缺点: Lettuce 是基于 Netty 的连接(StatefulRedisConnection),

Lettuce 是一个可伸缩的线程安全的 Redis 客户端,支持同步、异步和响应式模式。

多个线程可以共享一个连接 实例,而不必担心多线程并发问题。

它基于优秀 Netty NIO 框架构建,支持 Redis 的高级功能,如 Sentinel,集 群,流水线,自动重新连接和

Redis 数据模型。

六、测试环境测试环境是否搭建成功

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringDataRedisApplication.class)
public class SpringDataRedisApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void initconn() {ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();ops.set("username","lisi");ValueOperations<String, String> value = redisTemplate.opsForValue();value.set("name","wangwu");System.out.println(ops.get("name"));}
}

七、SpringDataRedis序列化模板

1. 序列化问题

默认情况下的模板 RedisTemplate,

默认序列化使用的是JdkSerializationRedisSerializer,存储二进制字节码。

这时需要自定义模板,当自定义模板后又想存储 String 字符串时,可以使StringRedisTemplate的方式,他们俩

并不冲突。

要把 domain object 做为 key-value 对保存在 redis 中,就必须要解决对象的序列化问题。

Spring Data Redis给我们 提供了一些现成的方案:

2. 序列化解决方案

1. JdkSerializationRedisSerializer使用JDK提供的序列化功能。

优点:是反序列化时不需要提供类型信息(class),

但缺点是序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗 Redis 服务器的大量内存。

2. Jackson2JsonRedisSerializer 使用 Jackson 库将对象序列化为JSON字符串

优点:是速度快,序列化后的字符串短小精悍。

缺点:也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。

通过查看源代码,发现其只在反序列化过程中用到了类型信息。

3. GenericJackson2JsonRedisSerializer通用型序列化,这种序列化方式不用自己手动指定对象的 Class

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory){RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();//为string类型key设置序列器redisTemplate.setKeySerializer(new StringRedisSerializer());//为string类型value设置序列器redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());//为hash类型key设置序列器redisTemplate.setHashKeySerializer(new StringRedisSerializer());//为hash类型value设置序列器redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());redisTemplate.setConnectionFactory(redisConnectionFactory);return redisTemplate;}
}
//序列化
@Test
public void testSerial(){User user = new User();user.setId(1);user.setUsername("张三");user.setPassword("111");ValueOperations<String, Object> value = redisTemplate.opsForValue();value.set("userInfo",user);System.out.println(value.get("userInfo"));
}

3. 自定义序列化

RedisTemplate可以接收任意Object作为值写入Redis:

只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:

缺点:

  • 可读性差
  • 内存占用较大

我们可以自定义RedisTemplate的序列化方式,代码如下:

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){// 创建RedisTemplate对象RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置连接工厂template.setConnectionFactory(connectionFactory);// 创建JSON序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 设置Key的序列化template.setKeySerializer(RedisSerializer.string());template.setHashKeySerializer(RedisSerializer.string());// 设置Value的序列化template.setValueSerializer(jsonRedisSerializer);template.setHashValueSerializer(jsonRedisSerializer);// 返回return template;}
}

这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如图:

整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,

并且查询时能自动把JSON反序列化为Java对象。

不过,其中记录了序列化时对应的class名称,目的是为了查询时实现自动反序列化。

这会带来额外的内存开销。

4. StringRedisTemplate

为了节省内存空间,我们可以不使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储

String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

因为存入和读取时的序列化及反序列化都是我们自己实现的,SpringDataRedis就不会将class信息写入Redis了。

这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate,

它的key和value的序列化方式默认就是String方式。

省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:

@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON序列化工具
private static final ObjectMapper mapper = new ObjectMapper();@Test
void testSaveUser() throws JsonProcessingException {// 创建对象User user = new User("虎哥", 21);// 手动序列化String json = mapper.writeValueAsString(user);// 写入数据stringRedisTemplate.opsForValue().set("user:200", json);// 获取数据String jsonUser = stringRedisTemplate.opsForValue().get("user:200");// 手动反序列化User user1 = mapper.readValue(jsonUser, User.class);System.out.println("user1 = " + user1);
}

八、SpringData操作Redis

1. 操作string数据类型

// 1.操作String
@Test
public void testString() {ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();// 添加一条数据valueOperations.set("username", "zhangsan");valueOperations.set("age", "18");//redis中以层级关系、目录形式存储数据valueOperations.set("user:01", "lisi");valueOperations.set("user:02", "wangwu");// 添加多条数据Map<String, String> userMap = new HashMap<>();userMap.put("address", "bj");userMap.put("sex", "1");valueOperations.multiSet(userMap);// 获取一条数据Object username = valueOperations.get("username");System.out.println(username);// 获取多条数据List<String> keys = new ArrayList<>();keys.add("username");keys.add("age");keys.add("address");keys.add("sex");List<Object> resultList = valueOperations.multiGet(keys);for (Object str : resultList) {System.out.println(str);}// 删除redisTemplate.delete("username");
}

2. 操作hash数据类型

// 2.操作Hash
@Test
public void testHash() {HashOperations<String, String, String> hashOperations = redisTemplate.opsForHash();/** 添加一条数据*     参数一:redis的key*     参数二:hash的key*     参数三:hash的value*/hashOperations.put("userInfo","name","lisi");// 添加多条数据Map<String, String> map = new HashMap();map.put("age", "20");map.put("sex", "1");hashOperations.putAll("userInfo", map);// 获取一条数据String name = hashOperations.get("userInfo", "name");System.out.println(name);// 获取多条数据List<String> keys = new ArrayList<>();keys.add("age");keys.add("sex");List<String> resultlist =hashOperations.multiGet("userInfo", keys);for (String str : resultlist) {System.out.println(str);}// 获取Hash类型所有的数据Map<String, String> userMap = hashOperations.entries("userInfo");for (Entry<String, String> userInfo : userMap.entrySet()) {System.out.println(userInfo.getKey() + "--" + userInfo.getValue());}// 删除 用于删除hash类型数据hashOperations.delete("userInfo", "name");
}

3. 操作list数据类型

// 3.操作list
@Test
public void testList() {ListOperations<String, Object> listOperations = redisTemplate.opsForList();// 左添加(上)// listOperations.leftPush("students", "Wang Wu");// listOperations.leftPush("students", "Li Si");// 左添加(上) 把value值放到key对应列表中pivot值的左面,如果pivot值存在的话// listOperations.leftPush("students", "Wang Wu", "Li Si");// 右添加(下)// listOperations.rightPush("students", "Zhao Liu");// 获取 start起始下标 end结束下标 包含关系List<Object> students = listOperations.range("students", 0,2);for (Object stu : students) {System.out.println(stu);}// 根据下标获取Object stu = listOperations.index("students", 1);System.out.println(stu);// 获取总条数Long total = listOperations.size("students");System.out.println("总条数:" + total);// 删除单条 删除列表中存储的列表中几个出现的Li Si。listOperations.remove("students", 1, "Li Si");// 删除多条redisTemplate.delete("students");
}

4. 操作set数据类型

// 4.操作set-无序
@Test
public void testSet() {SetOperations<String, Object> setOperations = redisTemplate.opsForSet();// 添加数据String[] letters = new String[]{"aaa", "bbb", "ccc", "ddd", "eee"};//setOperations.add("letters", "aaa", "bbb", "ccc", "ddd", "eee");setOperations.add("letters", letters);// 获取数据Set<Object> let = setOperations.members("letters");for (Object letter: let) {System.out.println(letter);}// 删除setOperations.remove("letters", "aaa", "bbb");
}

5. 操作sortedset数据类型

// 5.操作sorted set-有序
@Test
public void testSortedSet() {ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();ZSetOperations.TypedTuple<Object> objectTypedTuple1 = new DefaultTypedTuple<Object>("zhangsan", 7D);ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<Object>("lisi", 3D);ZSetOperations.TypedTuple<Object> objectTypedTuple3 = new DefaultTypedTuple<Object>("wangwu", 5D);ZSetOperations.TypedTuple<Object> objectTypedTuple4 = new DefaultTypedTuple<Object>("zhaoliu", 6D);ZSetOperations.TypedTuple<Object> objectTypedTuple5 = new DefaultTypedTuple<Object>("tianqi", 2D);Set<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<ZSetOperations.TypedTuple<Object>>();tuples.add(objectTypedTuple1);tuples.add(objectTypedTuple2);tuples.add(objectTypedTuple3);tuples.add(objectTypedTuple4);tuples.add(objectTypedTuple5);// 添加数据zSetOperations.add("score", tuples);// 获取数据Set<Object> scores = zSetOperations.range("score", 0, 4);for (Object score: scores) {System.out.println(score);}// 获取总条数Long total = zSetOperations.size("score");System.out.println("总条数:" + total);// 删除zSetOperations.remove("score", "zhangsan", "lisi");
}

6. 获取所有key+设置key失效时间

获取所有key&删除

// 获取所有key
@Test
public void testAllKeys() {// 当前库key的名称Set<String> keys = redisTemplate.keys("*");for (String key: keys) {System.out.println(key);}
}
// 删除
@Test
public void testDelete() {// 删除 通用 适用于所有数据类型redisTemplate.delete("score");
}

设置key的失效时间

@Test
public void testEx() {ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();// 方法一:插入一条数据并设置失效时间valueOperations.set("code", "abcd", 180, TimeUnit.SECONDS);// 方法二:给已存在的key设置失效时间boolean flag = redisTemplate.expire("code", 180, TimeUnit.SECONDS);// 获取指定key的失效时间Long l = redisTemplate.getExpire("code");
}

7. 通用操作

/*** 通用操作,针对不同的数据类型都可以操作
*/
@Test
public void testCommon(){//获取Redis中所有的keySet<String> keys = redisTemplate.keys("*");for (String key : keys) {System.out.println(key);}//判断某个key是否存在Boolean project = redisTemplate.hasKey("itcast");System.out.println(project);//删除指定keyredisTemplate.delete("myZset");//获取指定key对应的value的数据类型DataType dataType = redisTemplate.type("myset");System.out.println(dataType.name());}

九、SpringDataRedis整合哨兵

application.yml

spring:redis:# Redis服务器地址host: 192.168.10.100# Redis服务器端口port: 6379# Redis服务器端口password: root# Redis服务器端口database: 0# 连接超时时间timeout: 10000mslettuce:pool:# 最大连接数,默认8max-active: 1024# 最大连接阻塞等待时间,单位毫秒,默认-1msmax-wait: 10000ms# 最大空闲连接,默认8max-idle: 200# 最小空闲连接,默认0min-idle: 5#哨兵模式sentinel:#主节点名称master: mymaster#节点nodes:  192.168.10.100:26379,192.168.10.100:26380,192.168.10.100:26381

Bean注解配置

@Bean
public RedisSentinelConfiguration redisSentinelConfiguration(){RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()// 主节点名称.master("mymaster")// 主从服务器地址.sentinel("192.168.10.100", 26379).sentinel("192.168.10.100", 26380).sentinel("192.168.10.100", 26381);// 设置密码sentinelConfig.setPassword("root");return sentinelConfig;
}

十、知识小结

SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做

SpringDataRedis,官网地址:Spring Data Redis

  • 提供了对不同Redis客户端的整合(Lettuce和Jedis)
  • 提供了RedisTemplate统一API来操作Redis
  • 支持Redis的发布订阅模型
  • 支持Redis哨兵和Redis集群
  • 支持基于Lettuce的响应式编程
  • 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
  • 支持基于Redis的JDKCollection实现

SpringDataRedis中提供了RedisTemplate工具类,其中封装了各种对Redis的操作。

并且将不同数据类型的操作API封装到了不同的类型中:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/55095.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

助农小程序|助农扶贫系统|基于java的助农扶贫系统小程序设计与实现(源码+数据库+文档)

助农扶贫系统小程序 目录 基于java的助农扶贫系统小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 5.1.1 农户管理 5.1.2 用户管理 5.1.3 订单统计 5.2.1 商品信息管理 5.3.1 商品信息 5.3.2 订单信息 5.3.3 商品评价 5.3.4 商品退货 四、数据库设计 1、…

水波荡漾效果+渲染顺序+简单UI绘制

创建场景及布置 创建新场景Main,在Main场景中创建一个plane物体&#xff0c;命名为WaterWavePla,具体数值及层级面板排布如下&#xff1a; 编写脚本 创建一个文件夹&#xff0c;用于存放脚本&#xff0c;命名Scripts,创建一个子文件夹Effect,存放特效相关脚本&#xff0c;创建…

WAF,全称Web Application Firewall,好用WAF推荐

WAF&#xff0c;全称Web Application Firewall&#xff0c;即Web应用防火墙&#xff0c;是一种网络安全设备&#xff0c;旨在保护Web应用程序免受各种Web攻击&#xff0c;如SQL注入、跨站脚本&#xff08;XSS&#xff09;、跨站请求伪造&#xff08;CSRF&#xff09;等。 WAF通…

前端面试经验总结2(经典问题篇)

谈谈你对前端的理解 前端主要负责产品页面部分的实现&#xff0c;是最贴近于用户的程序员。 基本工作要求&#xff1a; 1.参与项目&#xff0c;通过与团队成员&#xff0c;UI设计&#xff0c;产品经理的沟通&#xff0c;快速高质量的实现效果图&#xff0c;并能够精确到1px 2.做…

数学建模研赛总结

目录 前言进度问题四分析问题五分析数模论文经验分享总结 前言 本文为博主数学建模比赛第五天的内容记录&#xff0c;希望所写的一些内容能够对大家有所帮助&#xff0c;不足之处欢迎大家批评指正&#x1f91d;&#x1f91d;&#x1f91d; 进度 今天已经是最后一天了&#xf…

COMP 6714-Info Retrieval and Web Search笔记week2

tokenizer&#xff1a;分词器 右半部分&#xff1a;倒排索引 Westlaw AND&#xff08;&&#xff09;&#xff1a; 要搜索必须同时出现在文档中的两个或多个词语&#xff0c;请使用 AND&#xff08;&&#xff09;。例如&#xff0c;输入 narcotics & warrant&#x…

基于单片机的催眠电路控制系统

** 文章目录 前言一 概要功能设计设计思路 软件设计效果图 程序文章目录 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主…

【2024工业3D异常检测文献】CMDIAD: 基于跨模态蒸馏驱动的多模态工业异常检测

Incomplete Multimodal Industrial Anomaly Detection via Cross-Modal Distillation 1、Background 近年来&#xff0c;基于3D点云和RGB图像的多模态工业异常检测(IAD)研究强调了利用模态间的冗余性和互补性对于精确分类和分割的重要性。 在项目中&#xff0c;提出了CMDIAD方…

如何在算家云搭建MVSEP-MDX23(音频分离)

一、MVSEP-MDX23简介 模型GitHub网址&#xff1a;MVSEP-MDX23-music-separation-model/README.md 在 main ZFTurbo/MVSEP-MDX23-音乐分离模型 GitHub 上 在音视频领域&#xff0c;把已经发布的混音歌曲或者音频文件逆向分离一直是世界性的课题。音波混合的物理特性导致在没有…

js列表数据时间排序和取唯一值

1.取唯一值[...new Set(array)] const array [1, 2, 3, 2, 4, 5, 3, 5]; // 使用Set去除重复元素 const uniarray [...new Set(array)]; console.log(uniarray); // 输出: [1, 2, 3, 4, 5] 2.排序 var u [1,3,2,5,4]; var uu u.sort(); console.log(uu); var u [1,3…

【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第四篇-着色器投影-接收阴影部分】

上一章中实现了体积渲染的光照与自阴影&#xff0c;那我们这篇来实现投影 回顾 勘误 在开始本篇内容之前&#xff0c;我已经对上一章中的内容的错误进行了修改。为了确保不会错过这些更正&#xff0c;同时也避免大家重新阅读一遍&#xff0c;我将在这里为大家演示一下修改的…

算法分析——《二分查找》

&#x1f6e9;《二分查找》 &#x1f3a8;题目描述&#xff1a; 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在返回下标&#xff0c;否则返回 -1。 示例 …

Java基础(Arrays工具类)(asList()方法)(详细)

目录 一、Arrays工具类 &#xff08;1&#xff09;引言 &#xff08;2&#xff09;基本介绍 &#xff08;3&#xff09;主要功能&#xff08;提供的方法&#xff09; &#xff08;I&#xff09;排序&#xff08;Arrays.sort()&#xff09; &#xff08;II&#xff09;搜索(查找…

怎么给视频加片头片尾和字幕

在这个视觉内容爆炸的时代&#xff0c;一段精心制作的视频不仅能吸引眼球&#xff0c;更能传达深刻的情感与信息。而一个引人入胜的片头、一个温馨感人的片尾&#xff0c;以及恰到好处的字幕&#xff0c;无疑是提升视频质感的关键。那么新人要怎么给视频加片头片尾和字幕效果呢…

Springboot项目-实战2-实现

文章目录 接口接收数据并进行数据清洗mysql读取到redis接口返回参数对象java函数使用备注返回参数分析stream操作Thread线程队列集合存储统计加密日志以及aspect对接口的时间影响&#xff1f;war包和jar包的区别&#xff1f;filter、interceptor、aspect区别&#xff1f;探针Gs…

如何在 Kubernetes 上部署和配置开源数据集成平台 Airbyte?

在 Kubernetes 上部署和配置 Airbyte 是一个复杂但非常有价值的过程&#xff0c;特别是对于需要强大数据集成和数据处理能力的企业或团队。Airbyte 是一个开源的数据集成平台&#xff0c;允许用户从各种来源提取数据并加载到目标存储中。其强大的插件系统支持多种数据源与目标&…

C语言 | Leetcode C语言题解之第440题字典序的第K小数字

题目&#xff1a; 题解&#xff1a; #define MIN(x, y) ((x) < (y) ? (x) : (y))int getSteps(int curr, long n) {int steps 0;long first curr;long last curr;while (first < n) {steps MIN(last, n) - first 1;first first * 10;last last * 10 9;}return …

QT使用qss控制样式实现动态换肤

文章目录 设计QSS样式表动态加载QSS文件主函数调用QT提供了一种非常灵活的方式来使用QSS(Qt Style Sheet,类似于 CSS 的样式表),实现界面的动态换肤功能。QSS可以改变Qt应用程序中几乎所有可视组件的外观,包括颜色、字体、边框等。下面介绍一下如何通过QSS实现动态换肤。 设…

诗画紫砂壶

大家详细解答一首网络上流传的顺口溜&#xff0c;其中包含了很多的紫砂壶型。 // 紫砂壶型 // 秦权汉瓦唐羽仙&#xff0c;西施文旦美人肩。 逸公德钟对却月&#xff0c;仿鼓虚扁望方山。东坡提梁卧井栏&#xff0c;供春提璧看柿圆。荷花海棠吹松段。掇只君乐奏合欢&#xff…

vue3中< keep-alive >页面实现缓存及遇到的问题

vue3中< keep-alive >页面实现缓存及遇到的问题 实现原理&#xff1a;keep-alive 是 Vue 的内置组件&#xff0c;当它包裹动态组件时&#xff0c;会缓存不活动的组件实例&#xff0c;而不是销毁它们。实现不同路由是否缓存只需要设置对应路由参数keepAlive为true&#xf…