Redis基础语法和SpringBoot集成使用

news/2024/11/7 10:56:42/

在初期,已经讲述了Redis安装问题。现在正式进入Redis的入门阶段。

Redis客户端

命令行客户端

redis-cli [options] [commands]

常用到的 options 有:

  • -h 127.0.0.1: 指定要连接的Redis的IP地址【默认127.0.0.1】
  • -p 6379: 指定连接Redis的端口【默认6379】
  • -a 123456: 输入Redis的链接密码

commands 就是操作 Redis 的命令

  • ping: 与 Redis 服务端做心跳测试,服务端会正常返回 PONG
    在这里插入图片描述

设置了密码之后就需要通过密码验证才能使用redis命令行客户端

图形化界面客户端

用的是csdn的github加速计划,所以不用担心无法访问问题
Win免费下载使用Resp.app
在这里插入图片描述
Mac需要付费订阅下载Resp,app
在这里插入图片描述

在这里插入图片描述

Redis常用基础命令

常用命令不需要记忆,需要的时候查询手册即可

Redis通用命令

通用的命令常见的有

  • KEYS:查看符合模板的所有key
  • DEL:删除一个指定的key
  • EXISTS:判断key是否存在
  • EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除
  • TTL:查看一个KEY的剩余有效期

通过 help 命令帮助这些命令的使用
在这里插入图片描述

String类型

String字符串是Redis最简单的存储类型。
根据字符串格式不同,可以分为3类

  • String:普通字符串
  • int:整形,可自增、自减操作
  • float:整形,可自增、自减操作
    不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过512MB
KEYVALUE
name张三
num1
price1.1

常用语法

语法含义
SET添加/修改 已经存在的一个String 类型的键值对
GET根据 KEY 获取 VALUE
MSET批量添加多个 String 类型键值对
MGET根据多个 KEY 获取多个 String 类型的 VALUE
INCR让一个整形的 KEY 自增/自减
INCRBY让一个整形的 KEY 自增指定大小【INCRBY num -2:num -= 2】
INCRBYFLOAT让一个浮点型数据自增
SETNX添加一个 String 类型键值对,前提是这个 KEY 不存在,否则不执行
SETEX添加一个 String 类型键值对,并且指定有效期

KEY 结构

Redis没有MySQL中Table表的概念。如何区分不同类型的 KEY 呢?
比如存储一个ID都为1的用户数据和文章数据,那么 SET ID 1 就会冲突。解决方案是:多个单词之间用 : 分隔开,格式如下:

项目名:业务名:类型:id

user相关的key:BlogSystem:user:1
文章相关的key:BlogSystem:article:1

如果VALUE是一个对象,则可以将对象序列化为JSON字符串后存储

KEYVALUE
BlogSystem:user:1{“id”:1, “name”: “张三”, “age”:13}
BlogSystem:article:1“id”:1, “title”: “Redis快速入门”, “updateTime”: “2022-12-23”

在这里插入图片描述

Hash类型

String结构将对象序列化为JSON格式存储后,当需要修改某个字段是很不方便。
Hash结构可以将对象字段单独存储,方便修改

KEYFILEDVALUE
BlogSystem:user:1name“张三”
BlogSystem:user:1age13
BlogSystem:user:2name“李四”
BlogSystem:user:2age14

Hash常用语法

语法含义
HSET key field value添加或者修改hash类型key的field的值
HGET key field获取一个hash类型key的value
HMSET批量添加多个hash类型key的field的值
HMGET批量获取多个hash类型key的field的值
HGETALL获取一个hash类型的key中的所有的field和value
HKEYS获取一个hash类型的key中所有的field
HINCRBY让一个hash类型key的value自增指定步长
HSETNX添加一个hash类型的key的field之,前提是这个field不存在否则不执行

List类型

Redis中的List类型与Java中的LinkedList类似,可以看作是一个双向链表结构。既可以支持正向检索也支持反向检索。
特征与LinkedList类似:

  • 有序
  • 元素可以重复
  • 插入和删除快
  • 查询一般

用来存储一个有序数据。例如:朋友圈点赞列表,评论列表

常用语法

语法含义
LPUSH key element在列表左侧插入一个或多个元素
RPUSH key element向列表右侧插入一个或多个元素
LPOP key移除并返回列表左侧的第一个元素,没有则返回nil
RPOP key移除并返回列表右侧的第一个元素,没有则返回nil
BLPOP和BRPOP与LPOP和RPOP类似,只不过在没有元素时等待指定时间而不是直接返回nil
LRANGE key star end返回一段表范围内的所有元素【0下标开始计算】

Set类型

Redis的Set结构与Java中的HashSet类似,可以看作是一个value为null的HashMap。

  • 无序
  • 不可重复
  • 查找快
  • 支持交并补查询

Set常用语法

语法含义
SADD key member向set中添加一个或多个元素
SREM key element移除set中的指定元素
SCARD key返回set中元素的个数
SISMEMBER key member判断一个元素是否存在于set中
SMEMBERS获取set中所有元素
SINTER key1 key2key1 和 key2 交集
SDIFF key1 key2key1 和 key2 差集集

SortedSet类型

Redis的SortedSet是一个可排序的Set集合。与Java中的TreeSet类似,但底层数据结构差异很大。SortedSet中的每个元素都带有score属性,可以基于score属性对元素排序,底层是一个调表(SkipList)+Hash表

  • 可排序
  • 不可重复
  • 查询快

因为SortedSet可排序特性,经常用来实现排行榜这样的功能

SortedSet常用语法

语法含义
ZADD key score member添加一个或多个元素到SortedSet,如果已经存在则更新其score值
ZREM key member删除SortedSet中指定元素的score值
ZSCORE key member获取SortedSet中指定元素的score值
ZRANK key member获取SortedSet中指定元素排名【升序】
ZREVRANK key member获取SortedSet中指定元素排名【降序】
ZCOUNT key min max统计score值在给定范围内的所有元素的个数
ZINCRBY key increment member让SortedSet中指定元素自增,步长为指定的increment值
ZRANGE key min max按照score排序后,获取指定排名范围内的元素
ZRANGEBYSCORE key min max按照score排序后,获取指定score范围内的元素
ZINTER,ZUNION,ZDIFF交并差

Redis的Java客户端

Jedis快速入门

在这里插入图片描述

  • Jedis和Lettuce:这两个主要是提供了Redis命令对应的API,方便操作Redis。而SpringDataRedis又针对这两种做了抽象和封装
  • Jedis:语法和Redis类似,优点是使用快捷缺点是多线程环境下会出现不安全
  • Lettuce:依靠opsForXxx进行操作Redis数据库,可解决多线程不安全情况
  • Redisson:是在Redis基础上实现了分布式的可伸缩的Java数据结构。例如Map、Queue等。而且支持跨进程的同步机制:Lock、Semaphore等待,比较适合用来实现特殊功能需求

创建一个Maven项目,引入需要的依赖
Jedis官网

<!-- redis依赖 -->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version>
</dependency>
<!-- 测试依赖 -->
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.9.1</version><scope>test</scope>
</dependency>

一个redis小测试

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;import java.util.Map;public class JedisTest {private Jedis jedis;@BeforeEachvoid setUp() {// 1.建立连接jedis = new Jedis("127.0.0.1", 6379);// jedis = JedisConnectionFactory.getJedis();// 2.设置密码jedis.auth("123456");// 3.选择数据库jedis.select(0);}@AfterEachvoid close() {if (jedis != null) {jedis.close();}}@Testvoid testString() {// 存数据String result = jedis.set("name", "张三");System.out.println("result = " + result);// 取数据String name = jedis.get("name");System.out.println("name = " + name);}@Testvoid testHash() {jedis.hset("user:1", "name", "张三");jedis.hset("user:1", "age", "13");jedis.hset("user:1", "sex", "male");Map<String, String> map = jedis.hgetAll("user:1");System.out.println(map);}
}

打开客户端可以看到已经成功插入String和Hash类型的数据
在这里插入图片描述
在这里插入图片描述

由于经常的断开连接,建立连接会有消耗。所以以创建一个连接池

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;public class JedisConnectionFactory {private static final JedisPool jedisPool;static {// 配置连接池JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();// 最大连接数jedisPoolConfig.setMaxTotal(10);// 最大空闲连接jedisPoolConfig.setMaxIdle(10);// 最小空闲连接jedisPoolConfig.setMinIdle(0);// 等待空闲时间[ms]jedisPoolConfig.setMaxWaitMillis(100);// 创建连接池对象,参数:连接池配置,服务端IP,服务端接口,超时时间,密码jedisPool = new JedisPool(jedisPoolConfig, "127.0.0.1", 6379, 100, "123456");}public static Jedis getJedis() {return jedisPool.getResource();}
}

SpringDataRedis客户端

SpringDataRedis官网简介
可以看到Redis的支持
在这里插入图片描述

创建一个Spring项目,添加如下依赖
在这里插入图片描述
yml配置如下

spring:redis:host: 127.0.0.1port: 6379password: Cxf@19307193096lettuce:pool:max-active: 8 #最大连接数max-idle: 8 #最大空闲连接min-idle: 0 #最小空闲连接max-wait: 1000ms #超时时间

测试代码如下

package app;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;@SpringBootTest
class TestRedisTemplate {private RedisTemplate redisTemplate;@Autowiredpublic TestRedisTemplate(RedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}@Testpublic void testString() {// 写入一条 String 数据redisTemplate.opsForValue().set("name", "张三");// 获取一条 String 数据Object name = redisTemplate.opsForValue().get("name");System.out.println(name);}
}

在这里插入图片描述

会发现已经是乱码,可读性很差,因此需要用到Redis的序列化。那么问题出现在哪儿呢?我们顺着RedisTemplate 部分源码阅读一下
在这里插入图片描述
主要是 key和value 的序列化。redis中key一般用的都是字符串类型,因此使用的是String类型的序列化
程序会先通过 afterPropertiesSet 确定序列化方式
在这里插入图片描述
查看默认的 defaultSerializer 的属性如下所示,是一个 null 。所以会使用默认的 JDK序列化工具
在这里插入图片描述
我们再看 this.defaultSerializer = new JdkSerializationRedisSerializer(this.classLoader != null ? this.classLoader : this.getClass().getClassLoader()); 方法
在这里插入图片描述
再看 (new SerializingConverter() 代码
在这里插入图片描述
再看 new DefaultSerializer() 代码
在这里插入图片描述
再看 serialize() 用的是 ObjectOutPutStream 序列化
在这里插入图片描述
上面了解了 JDK的序列化方式,SpringDataRedis集成了众多序列化工具,默认使用的是JDK序列化方式,对于普通对象而言使用则会出现一定乱码问题,SpringDataRedis更推荐使用大名鼎鼎的 Jackson 进行对对象序列化
在这里插入图片描述

自定义 Redis 的序列化器

package app.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {// 1.创建 RedisTemplate 对象RedisTemplate redisTemplate = new RedisTemplate();// 2.设置连接工厂redisTemplate.setConnectionFactory(redisConnectionFactory);// 创建 json 序列化工具GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 3.设置 key 序列化redisTemplate.setKeySerializer(RedisSerializer.string());redisTemplate.setHashKeySerializer(RedisSerializer.string());// 4.设置 value 序列化redisTemplate.setValueSerializer(jsonRedisSerializer);redisTemplate.setHashValueSerializer(jsonRedisSerializer);// 5.返回 RedisTemplatereturn redisTemplate;}
}

在这里插入图片描述
测试结果如下所示
在这里插入图片描述
我们再测试一下对象的存储结果
在这里插入图片描述
再去redis数据库中查看
在这里插入图片描述

在这里插入图片描述
说明:对于普通字符串 “张三” 直接按照String类型存入到了redis中;而对于 User 对象则被 Jackson 序列化为了为了 json 类型的数据,为了能够方便通过 json 数据返回序列化出 User 对象还会多存入一条属性 "@class": "app.pojo.User"。然而这样虽然反序列化方便了,但是数据量堆叠起来之后会给redis带了额外的内存开销

StringRedisTemplate 使用String序列化器

因此为了节省内存,一般并不会使用JSON序列化器,而是统一使用String序列化器,要求之存储String类型的key和value。当需要的时候在手动序列化或反序列化。
在这里插入图片描述
主要利用jackson的 ObjectMapper 类来实现手动的序列化和反序列化而不是通过Redis自带的JSON序列化工具

读写String

package app;import app.pojo.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;@SpringBootTest
public class TestStringRedisTemplate {private StringRedisTemplate stringRedisTemplate;private static final ObjectMapper mapper = new ObjectMapper();@Autowiredpublic TestStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {this.stringRedisTemplate = stringRedisTemplate;}@Testpublic void testString() {// 写入 String 数据stringRedisTemplate.opsForValue().set("name", "张三");// 读取 String 数据String name = stringRedisTemplate.opsForValue().get("name");System.out.println(name);}@Testpublic void testSaveUser() throws JsonProcessingException {// 创建对象User user = new User("李四", 24);// 手动序列化String json = mapper.writeValueAsString(user);// 写入 User 数据stringRedisTemplate.opsForValue().set("user", json);// 读取 User 数据String jsonUser = stringRedisTemplate.opsForValue().get("user");System.out.println("redis读取结果: " + jsonUser);// 手动反序列化user = mapper.readValue(jsonUser, User.class);System.out.println("jsonUser反序列化: " + user);}
}

会发现Redis在存储的时候已经消除掉多余的数据
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

读写Hash

在处理 Hash 类型的时候,语法hset有些不同,更偏向于 Java 语法 put

@Test
public void testSaveHash(){stringRedisTemplate.opsForHash().put("user:1", "name", "张三");stringRedisTemplate.opsForHash().put("user:1", "age", "23");// 获取单个字段String name = (String) stringRedisTemplate.opsForHash().get("user:1", "name");System.out.println(name);// 获取全部Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:1");System.out.println(entries);
}

在这里插入图片描述
在这里插入图片描述

总结
方案一

  1. 自定义 RedisTemplate
  2. 修改 RedisTemplate 序列化器为 GenericJackson2JsonRedisSerializer

方案二

  1. 使用 StringRedisTemplate
  2. json序列化处理之后再写入redis
  3. 读取完redis之后再json反序列化成对象

http://www.ppmy.cn/news/10345.html

相关文章

软件测试~自动化测试Seleniums---1

一.什么是自动化测试 1.自动化测试介绍 自动化测试指软件测试的自动化&#xff0c;在预设状态下运行应用程序或者系统&#xff0c;预设条件包括正常和异常&#xff0c;最后评估运行结果。将人为驱动的测试行为转化为机器执行的过程。 将测试人员双手解放&#xff0c;将部分测…

《元宇宙2086》影视工业弯道超车?《科普时报》刊登采访报道

科普时报-第267期 2023年01月06日 星期五 第05版&#xff1a;书香文史刊载了题目为“《元宇宙2086》影视工业弯道超车&#xff1f;”的关于高泽龙的采访报道。全文内容如下&#xff1a;在2022年中国金鸡百花电影节暨第35届中国电影金鸡奖期间&#xff0c;我创作的中国首部元宇宙…

人工智能导论实验——前馈神经网络

实验目的通过实验了解全连接神经网络的结构&#xff0c;应用全连接网络处理分类和回归任务。实验任务1&#xff09;初级实验&#xff1a;①手写体图像识别实验&#xff1b;②FashionMnist图像分类实验&#xff1b;③汽车里程数预测实验。2&#xff09;中级实验&#xff1a;①鸢…

通信电子、嵌入式类面试题刷题计划01

文章目录001——什么是奈奎斯特采样定理&#xff1f;002——有源滤波器和无源滤波器的区别是什么&#xff1f;003——什么是反馈电路&#xff1f;请举出相关应用004——什么是竞争冒险现象&#xff1f;如何消除和避免此类现象005——什么是基尔霍夫定理&#xff1f;006——if e…

NOTE:2022年11月27日以后精密星历采用长命名

IGS切换到新的参考框架—IGS20&#xff0c;以作为其产品的基础。IGS20 与 2022 年 4 月发布的 ITRF2020 密切相关。最新的卫星和地面天线校准 igs20.atx 也将同时生效&#xff0c;与 IGS20 一起使用。IGS 打算从 GPS 第 2238 周&#xff08;2022 年 11 月 27 日&#xff09;的产…

基于imx6ull第一个Linux驱动

在编译第一个驱动之前&#xff0c;需要把基本的环境准备好&#xff0c;可以参照这两篇文章&#xff1a;https://wlink.blog.csdn.net/article/details/128590747https://wlink.blog.csdn.net/article/details/128591216我们之前写过一个基于ubuntu最基本的字符设备驱动&#xf…

(mysql)table metadata lock原因及解决

背景在项目的一次需求中&#xff0c;需要对一个表增加字段&#xff0c;然而在执行增加字段的sql语句时&#xff0c;卡住了很久都没提交到Mysql完成&#xff0c;而此时对外接口服务请求也卡住了&#xff0c;这时中断卡住的alter table 语句&#xff0c;服务慢慢恢复正常&#xf…

Python 字符串连接的七种方式

1.’’ 号连接用 ‘’连接字符串应该是最基本的方式了&#xff0c;话不多说&#xff0c;直接上代码。>>> text1 "Hello" >>> text2 "World" >>> text1 text2 HelloWorld优点&#xff1a;容易记忆。缺点&#xff1a;性能较差…