重庆网站建设选卓光/网络营销策略分析报告
目录
讲解一:简介
讲解二: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封装到了不同的类型中:
相关文章:

Redis篇(Java操作Redis)
目录 讲解一:简介 讲解二:Jedis Github 一、创建项目、 二、添加依赖 三、配置文件 四、Java连接Redis 五、通过Redis连接池获取连接对象并操作服务器 六、封装JedisUtil对外提供连接对象获取方法 七、Java操作Redis五种数据类型 1. 连接与释放…...

Cypress自动化Github workflow
目录 Workflow .github/workflows/build.yaml jobs build-deploy: .github/wrokflows/execute-tests.yaml 输入参数 jobs restart_failed_dp: seed_data: execute-tests: Docker File docker/Dockerfile.base docker/service-dockerfile.base Deploy deploy/tes…...

Hbase高阶知识:HBase的协处理器(Coprocessor)原理、使用实例、高级技巧和案例分析
目录 第一章 Hbase概述与基础知识 1.1 HBase的架构与数据模型 1.2 什么是协处理器 1.3 协处理器的优势 第二章 协处理器的工作原理 2.1 协处理器的运行机制 2.2 协处理器的注册与监听 2.3 协处理器与RegionServer的交互 第三章 协处理器的类型 3.1 端点协处理器 3.2…...

海尔嵌入式硬件校招面试题及参考答案
使用 QT 的经验及对控件和信号与槽机制的了解 我使用 QT 有一段时间了,在项目开发中积累了较为丰富的经验。 QT 中的控件丰富多样,涵盖了各种常见的界面元素需求。例如按钮、文本框、列表框、进度条等。这些控件具有良好的可定制性,可以通过属性设置、样式表等方式来调整外观…...

Leetcode基础算法篇|202409(4)贪心算法
贪心算法(Greedy Algorithm):一种在每次决策时,总是采取在当前状态下的最好选择,从而希望导致结果是最好或最优的算法。 学习链接:leetcode-notes/docs/ch04/04.04/04.04.02-Exercises.md at main datawha…...

echarts 导出pdf空白原因
问题阐述 页面样式: 导出pdf: 导出pdf,统计图部分为空白。 问题原因 由于代码中进行了dom字符串的复制,而echarts用canvas绘制,canvas内部内容不会进行复制,只会复制canvas节点,因此导出pdf空白。 解决…...

数据结构及基本算法
目录 第一章 概论 第一节 引言 第二节 基本概念和常用术语 第三节 算法的描述与分析 第二章 线性表 第一节 线性表定义和基本运算个 一、线性表的逻辑定义 二、线性表的基本运算 第二节 线性表的顺序存储和基本运算的实现 一、线性表的顺序存储 二、顺序表上基本运算…...

vue3学习记录-computed
vue3学习记录-computed 1.为什么要用computed2.使用方法2.1 基本实例2.2 可写计算属性 1.为什么要用computed 写个购物车的案例 <script setup> import { ref, reactive,computed } from "vue" const tableData reactive([{ name: 商品1, price: 10, num: 1…...

SQLite3模块使用详解
目录 一、引言 1.1 SQLite3 简介 1.2 Python sqlite3 模块 二、连接数据库 2.1 导入 sqlite3 模块 2.2 连接数据库 2.3 创建游标对象 三、执行 SQL 语句 3.1 创建表 3.2 插入数据 3.3 查询数据 3.4 更新数据 3.5 删除数据 四、处理查询结果 4.1 fetchall() 4.2…...

防火墙详解(三)华为防火墙基础安全策略配置(命令行配置)
实验要求 根据实验要求配置防火墙: 合理部署防火墙安全策略以及安全区域实现内网用户可以访问外网用户,反之不能访问内网用户和外网用户均可以访问公司服务器 实验配置 步骤一:配置各个终端、防火墙端口IP地址 终端以服务器为例ÿ…...

假期学习--iOS中的static关键字
iOS中的static关键字 OC的static关键字 OC也提供了Static关键字,但是这个static关键字不能用于修饰成员变量,也就是说Static是不被允许修饰实例变量,同时Static关键字也不被允许修饰方法。Static关键字可以修饰全局变量,局部变量…...

Maya没有Arnold材质球
MAYA 没有Arnold材质球_哔哩哔哩_bilibili...

面试知识点总结篇三
一、arm中断流程和函数 ARM 中断流程 中断触发保存上下文中断向量表执行ISR - 清除中断标志恢复上下文返回中断 二、STM32任务间通信有哪些方式 消息队列、 信号量、共享内存、任务通知 三、uboot内存没驱动之前是怎么操作的 硬件初始化内存检测设置内存映射控制台初始化…...

数据加密标准(DES)详解:原理、步骤及Python实现
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storm…...

每日OJ_牛客_OR59字符串中找出连续最长的数字串_双指针_C++_Java
目录 牛客_OR59字符串中找出连续最长的数字串 题目解析 C代码1 C代码2 C代码3 Java代码 牛客_OR59字符串中找出连续最长的数字串 字符串中找出连续最长的数字串_牛客题霸_牛客网 题目解析 双指针: 遍历整个字符串,遇到数字的时候,用双…...

虚幻引擎UE5如何云渲染,教程来了
步骤一:获取云渲染权限 访问渲染101官网,使用云渲码6666进行注册。 下载并安装渲染客户端。 步骤二:设置渲染环境 确保云渲染环境与您的本地环境一致,避免出错。 步骤三:任务提交 完成环境配置后,解析…...

使用Python实现图形学光照和着色的光线追踪算法
目录 使用Python实现图形学光照和着色的光线追踪算法引言1. 光线追踪算法概述2. Python实现光线追踪算法2.1 向量类2.2 光源类2.3 材质类2.4 物体类2.5 光线追踪器类2.6 使用示例 3. 实例分析4. 光线追踪算法的优缺点4.1 优点4.2 缺点 5. 改进方向6. 应用场景结论 使用Python实…...

通过openAI的Chat Completions API实现一个支持追问的ChatGPT功能集成
文章目录 前言准备工作代码实现思路完整代码实现备注前言 本文介绍如何通过openAI的Chat Completions API实现一个支持追问的后台功能,追问打个比方,就是当你问了一句”窗前明月光的下一句是什么?“之后,想再往下问就可以直接问”再下一句呢?“,模型也能基于上下文理解你…...

8,STM32CubeMX配置SPI工程(读取norflash的ID)
1,前言 单片机型号:STM32F407 编程环境 :STM32CubeMX Keil v5 硬件连接 :SPI1,CS/SS--->PB14 注:本工程在1,STM32CubeMX工程基础(配置Debug、时钟树)基础上完…...

【MATLAB源码-第178期】基于matlab的8PSK调制解调系统频偏估计及补偿算法仿真,对比补偿前后的星座图误码率。
操作环境: MATLAB 2022a 1、算法描述 在通信系统中,频率偏移是一种常见的问题,它会导致接收到的信号频率与发送信号的频率不完全匹配,进而影响通信质量。在调制技术中,QPSK(Quadrature Phase Shift Keyi…...

AIGC学习笔记—minimind详解+训练+推理
前言 这个开源项目是带我的一个导师,推荐我看的,记录一下整个过程,总结一下收获。这个项目的slogan是“大道至简”,确实很简。作者说是这个项目为了帮助初学者快速入门大语言模型(LLM),通过从零…...

计算机毕业设计 在线项目管理与任务分配系统的设计与实现 Java实战项目 附源码+文档+视频讲解
博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…...

小程序用户截屏事件
原生小程序: wx.setScreenBrightness({value: 0.5 }); 参数值: value屏幕亮度值,范围 0~1,0 最暗,1 最亮 uniapp: uni.setScreenBrightness({value: 0.5 }); 参数值: value屏幕亮度值&a…...

HashMap为什么线程不安全?如何实现线程安全
HashMap线程不安全的原因主要可以从以下几个方面解释: 1. 数据覆盖 假设两个线程同时执行put操作,并且它们操作的键产生相同的哈希码,导致它们应该被插入到同一个桶中。以下是可能发生的情况: 线程A读取桶位置为空,准…...

Python爬虫之requests模块(一)
Python爬虫之requests模块(一) 学完urllib之后对爬虫应该有一定的了解了,随后就来学习鼎鼎有名的requests模块吧。 一、requests简介。 1、什么是request模块? requests其实就是py原生的一个基于网络请求的模块,模拟…...

当微服务中调度返回大数据量时如何处理
FeignClient 和 Dubbo 可能不是最佳选择。以下是一些适合处理大数据量的技术和方法: 消息队列 简介:消息队列是一种异步通信方式,用于在不同系统之间传递消息。常见的消息队列包括 RabbitMQ、Kafka、ActiveMQ 等。 优点:消息队列…...

【项目经验分享】深度学习点云算法毕业设计项目案例定制
以下是深度学习与点云算法相关的毕业设计项目案例,涵盖了点云数据的分类、分割、重建、配准、目标检测等多个领域,适用于智能驾驶、机器人导航、3D建模等多个应用场景: 案例截图: 基于PointNet的3D点云分类与分割PointNet在大规…...

【Redis 源码】2项目结构说明
1 文件目录结构 deps 这个目录主要包含 Redis 所依赖的第三方代码库。 Jemalloc,内存分配器,默认情况下选择该内存分配器来代替 Linux 系统的 libc-malloc,libc-malloc 性能不高,且碎片化严重。hiredis,这是官方 C 语…...

RP2040 C SDK GPIO和IRQ 唤醒功能使用
RP2040 C SDK GPIO和中断功能使用 SIO介绍 手册27页: The Single-cycle IO block (SIO) contains several peripherals that require low-latency, deterministic access from the processors. It is accessed via each processor’s IOPORT: this is an auxiliary…...

@Transactional导致数据库连接数不够
在Spring中进行事务管理非常简单,只需要在方法上加上注解Transactional,Spring就可以自动帮我们进行事务的开启、提交、回滚操作。甚至很多人心里已经将Spring事务Transactional划上了等号,只要有数据库相关操作就直接给方法加上Transactiona…...