Redisson 总结

1. 基础使用

1.1 引入依赖

<dependencies><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId></dependency>
</dependencies>

包含的依赖如下

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1.2 配置文件

其实默认主机就是 127.0.0.1,默认端口是 6379,一致的话可以不用配置

spring:data:redis:host: 127.0.0.1password: redis

1.3 测试类

import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RBucket<String> bucket = redissonClient.getBucket("test");bucket.set("hello");}@GetMapping("/get")public String get() {RBucket<String> bucket = redissonClient.getBucket("test");return bucket.get();}
}

1.4 测试

访问 /test 接口,利用 Redis 管理工具可以看到数据已经添加了进来

在访问 /get 接口,成功获取到数据

2. 设置序列化

上面可以看到在 Redis 管理工具中查看数据是一串字符,并不直观,可以自定义数据序列化

2.1 配置类

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient() {Config config = new Config();// 单机模式SingleServerConfig singleServerConfig = config.useSingleServer();singleServerConfig.setAddress("redis://127.0.0.1:6379");singleServerConfig.setPassword("redis");// JSON序列化config.setCodec(new JsonJacksonCodec());return Redisson.create(config);}
}

这里已经配置了主机等相关信息,因此配置文件里的配置可以去除,或者这里直接取配置文件的值,具体根据情况选择,其他的序列化类如下

编码类名称说明
org.redisson.codec.JsonJacksonCodecJackson JSON 编码
org.redisson.codec.AvroJacksonCodecAvro 一种二进制的 JSON 编码
org.redisson.codec.SmileJacksonCodecSmile一种 二进制的 JSON 编码
org.redisson.codec.CborJacksonCodecCBOR 一种二进制的 JSON 编码
org.redisson.codec.MsgPackJacksonCodecMsgPack 一种 二进制的 JSON 编码
org.redisson.codec.IonJacksonCodecAmazon Ion 亚马逊的 Ion 编码,格式与 JSON 类似
org.redisson.codec.KryoCodecKryo 二进制对象序列化编码
org.redisson.codec.SerializationCodecJDK 序列化编码
org.redisson.codec.FstCodecFST 10 倍于 JDK 序列化性能而且 100% 兼容的编码
org.redisson.codec.LZ4CodecLZ4 压缩型序列化对象编码
org.redisson.codec.SnappyCodecSnappy 另一个压缩型序列化对象编码
org.redisson.client.codec.JsonJacksonMapCodec基于 Jackson 的映射类使用的编码,可用于避免序列化类的信息,以及用于解决使用byte[] 遇到的问题
org.redisson.client.codec.StringCodec纯字符串编码(无转换)
org.redisson.client.codec.LongCodec纯整长型数字编码(无转换)
org.redisson.client.codec.ByteArrayCodec字节数组编码
org.redisson.codec.CompositeCodec用来组合多种不同编码在一起

2.2 测试

访问 /test 接口,再查看数据可以看到已经序列化成 JSON 格式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3. 基础数据结构使用

3.1 String

其实上面的示例用的就是字符串操作,通过 RBucket 对象来操作字符串数据结构

创建一个实体类

import lombok.Builder;
import lombok.Data;import java.io.Serial;
import java.io.Serializable;@Data
@Builder
public class Article implements Serializable {@Serialprivate static final long serialVersionUID = -8862397425409851538L;private String title;private String content;
}

存储对象,简单示例如下:

import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RBucket<Object> bucket = redissonClient.getBucket("test");bucket.set(Article.builder().title("demo").content("test redisson").build());}
}

数据如下:

3.2 Hash

通过 RMap 对象来操作哈希数据结构,简单示例如下:

import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RMap<String, Article> rMap = redissonClient.getMap("test");rMap.put("k1", Article.builder().title("demo").content("test redisson").build());}
}

数据如下:

3.3 List

3.3.1 无序

通过 RList 对象来操作列表数据结构,简单示例如下:

import org.redisson.api.RList;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RList<Article> rList = redissonClient.getList("test");rList.add(Article.builder().title("demo").content("test redisson").build());rList.add(Article.builder().title("demo").content("test redisson").build());}
}

数据如下:

3.3.2 有序

通过 RSortedSet 对象来操作有序集合数据结构

改造一下实体类,实现 Comparable 接口

import lombok.Data;import java.io.Serial;
import java.io.Serializable;@Data
public class Article implements Serializable, Comparable<Article> {@Serialprivate static final long serialVersionUID = -8862397425409851538L;private Long id;private String title;private String content;@Overridepublic int compareTo(Article article) {return this.getId().compareTo(article.getId());}
}

简单示例如下:

import org.redisson.api.RSortedSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RSortedSet<Article> rSortedSet = redissonClient.getSortedSet("test");Article article1 = new Article();article1.setId(22L);article1.setTitle("demo");article1.setContent("test redisson");rSortedSet.add(article1);Article article2 = new Article();article2.setId(11L);article2.setTitle("demo");article2.setContent("test redisson");rSortedSet.add(article2);}
}

数据如下,可以看到数据根据 id 排序

3.4 Set

通过 RSet 对象来操作集合数据结构,简单示例如下:

import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RSet<Article> rSet = redissonClient.getSet("test");rSet.add(Article.builder().title("demo").content("test redisson").build());rSet.add(Article.builder().title("demo").content("test redisson").build());}
}

数据如下,可以看到重复数据被去除了

3.5 Zset

通过 RScoredSortedSet 来操作带分数的有序集合数据结构,简单示例如下:

import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RScoredSortedSet<String> rScoredSortedSet = redissonClient.getScoredSortedSet("test");rScoredSortedSet.add(600.1, "test1");rScoredSortedSet.add(500.3, "test2");rScoredSortedSet.add(900.3, "test3");rScoredSortedSet.add(200.9, "test1");}
}

数据如下,可以看到根据分数来排序,并且重复数据被排除了

4. 布隆过滤器

可以用于检索一个元素是否在一个集合中

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.Duration;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RBloomFilter<String> rBloomFilter = redissonClient.getBloomFilter("test");// 初始化预期插入的数据量为10000和期望误差率为0.01rBloomFilter.tryInit(10000, 0.01);// 插入部分数据rBloomFilter.add("100");rBloomFilter.add("200");rBloomFilter.add("300");// 设置过期时间rBloomFilter.expire(Duration.ofSeconds(30));// 判断是否存在System.out.println(rBloomFilter.contains("300")); // trueSystem.out.println(rBloomFilter.contains("200")); // trueSystem.out.println(rBloomFilter.contains("999")); // false}
}

5. 分布式自增 ID

参考代码如下:

import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RAtomicLong rAtomicLong = redissonClient.getAtomicLong("test");System.out.println(rAtomicLong.incrementAndGet());}
}

6. 分布式锁

6.1 未加锁情况

模拟一个库存扣减操作

import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RBucket<Integer> bucket = redissonClient.getBucket("num");Integer num = bucket.get();if (num > 0) {System.out.println("扣减库存, 当前库存: " + --num);bucket.set(num);} else {System.out.println("库存不足");}}
}

使用 Jemter 模拟并发场景

点击运行后可以看到明显出现了并发问题

6.2 加锁情况

修改下库存扣减代码

import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RLock rLock = redissonClient.getLock("test");try {rLock.lock();RBucket<Integer> bucket = redissonClient.getBucket("num");Integer num = bucket.get();if (num > 0) {System.out.println("扣减库存, 当前库存: " + --num);bucket.set(num);} else {System.out.println("库存不足");}} finally {rLock.unlock();}}
}

再次模拟并发请求,可以看到问题已经解决

6.3 加锁操作耗时长

当加锁操作耗时较长时,如果多个请求进来,其他的请求会一直堵塞,可以使用 tryLock 来尝试获取锁,获取不到先返回响应

import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final RedissonClient redissonClient;@Autowiredpublic DemoController(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@GetMapping("/test")public void test() {RLock rLock = redissonClient.getLock("test");try {if (rLock.tryLock()) {RBucket<Integer> bucket = redissonClient.getBucket("num");Integer num = bucket.get();Thread.sleep(5000);if (num > 0) {System.out.println("扣减库存, 当前库存: " + --num);bucket.set(num);} else {System.out.println("库存不足");}} else {System.out.println("请稍后再试");}} catch (InterruptedException e) {System.out.println(e.getMessage());Thread.currentThread().interrupt();} finally {// 是否是锁定状态且是当前执行线程的锁if (rLock.isLocked() && rLock.isHeldByCurrentThread()) {rLock.unlock();}}}
}

模拟并发请求,这里将时间设置长一点,可以看到获取到锁的请求则去进行库存扣减,获取不到先返回响应

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

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

相关文章

Java基础总结(2)

1.实例方法和静态方法的区别 调用方式不同&#xff1a;静态方法可以通过类名.方法名直接调用&#xff0c;也可以通过当前类的实例对象.方法名来调用&#xff0c;但是实例方法只能通过后者来访问访问类的成员存在限制&#xff1a;在静态方法内部&#xff0c;只能访问类的静态成员…

【计网】从零开始掌握序列化 --- JSON实现协议 + 设计 传输\会话\应用 三层结构

唯有梦想才配让你不安&#xff0c; 唯有行动才能解除你的不安。 --- 卢思浩 --- 从零开始掌握序列化 1 知识回顾2 序列化与编写协议2.1 使用Json进行序列化2.2 编写协议 3 封装IOService4 应用层 --- 网络计算器5 总结 1 知识回顾 上一篇文章我们讲解了协议的本质是双方能够…

WPF DataGrid 单元格居中,头部居中,点击行改变背景色。

我得全局样式都写在了App.XAML文件下的ResourceDictionary里&#xff0c;方便全局引用 DataGrid样式和点击改变行背景色的触发器(BasedOn继承的是UI框架的样式&#xff0c;若无则删除&#xff0c;触发器还有鼠标移动事件等&#xff0c;按需自行修改添加) <Style x:Key&quo…

安卓13长按电源按键直接关机 andriod13不显示关机对话框直接关机

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 有些设备需要在长按电源键的时候,直接关机。不需要弹出对话框进行询问。 2.问题分析 过滤电源按键,需要在系统里面处理的话,那么我们需要熟悉android的事件分发,然后再…

Golang | Leetcode Golang题解之第420题强密码检验器

题目&#xff1a; 题解&#xff1a; func strongPasswordChecker(password string) int {hasLower, hasUpper, hasDigit : 0, 0, 0for _, ch : range password {if unicode.IsLower(ch) {hasLower 1} else if unicode.IsUpper(ch) {hasUpper 1} else if unicode.IsDigit(ch)…

【2025】儿童疫苗接种预约小程序(源码+文档+解答)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

hackmyvm靶场--zon

环境 攻击机kali 靶机 未知 主机探测 因为在同一个局域网内使用ARP协议探测存活主机 靶机为192.168.56.128 端口探测 常见的80和22端口 那么一定是寻找web漏洞拿shell了 后台扫描 后台扫描常用dirsearch和gobuster,有时候小字典可能不太行&#xff0c;可以尝试换个大点…

使用AVL树实现Map

一、数组在裂变扩容时可能会出现环、在数组元素转为链表之后选择尾插法插入节点、数组到链表到AVL到RBT的转换 1、数组在裂变扩容时链表中的节点计算出来的位置可能也会发生变化&#xff0c;在多线程情况下调整节点位置可能会出现环。 2、数组中的数组元素转为链表后插入新节点…

设计模式 享元模式(Flyweight Pattern)

享元模式 简绍 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;它的目的是通过共享技术来有效地支持大量细粒度的对象。享元模式可以极大地减少内存的使用&#xff0c;从而提高程序的性能。它特别适用于需要创建大量相似对象的场景&#…

Cypress安装与启动(开始学习记录)

一 Cypress安装 使用npm安装 1.查看node.js npm的版本&#xff0c;输入 npm --version 和 node --version&#xff0c;node.js没安装的可以去中文网下载最新稳定版安装&#xff0c;npm不建议升级到最新版本&#xff0c;会导致安装Cypress时Error: Cannot find module ansi-st…

在已安装的openresty上添加安装upstream模块报错的解决以及使用Consul服务发现时定时变更nginx的upstream的shell脚本

一、在已经安装好的openresty环境上添加安装upstream模块报错&#xff1a; 在已经安装好的openresty环境上添加安装upstream模块报错&#xff1a;http upstream check module can not find any check server, make sure you ve added the check 的问题解决。 服务器上已经安装好…

idea中java及java web项目的常见问题

1、乱码问题&#xff0c;主要有几处地方&#xff0c;需要检查。 ①确保文件编码&#xff0c;其实主要就是在idea启动文件中&#xff0c;增加了 -Dfile.encodingUTF-8的设置 ②编辑器默认编码&#xff0c;都改为UTF-8 ③Tomcat的运行配置&#xff0c;编码也改为UTF-8,同样使用…

SpringBoot3核心特性-核心原理

目录 传送门前言一、事件和监听器1、生命周期监听2、事件触发时机 二、自动配置原理1、入门理解1.1、自动配置流程1.2、SPI机制1.3、功能开关 2、进阶理解2.1、 SpringBootApplication2.2、 完整启动加载流程 三、自定义starter1、业务代码2、基本抽取3、使用EnableXxx机制4、完…

zynq的PS端mac与RTL8211F的连接要点

目录 1 VCCO_MIO12 PS_MIO_VREF3 PS的引脚4 RXDLY TXDLY5 ZYNQ的MAC可以调整延时吗 1 VCCO_MIO1 接1.8V 2 PS_MIO_VREF 接0.9V&#xff0c;可通过电阻分压 可通过电阻分压 3 PS的引脚 4 RXDLY TXDLY RXDLY RXD[0] TXDLY RXD[1] 与XC7Z020的PS端MAC连接&#xff0c;必须…

CVE-2024-2389 未经身份验证的命令注入

什么是 Progress Flowmon? Progress Flowmon 是一种网络监控和分析工具,可提供对网络流量、性能和安全性的全面洞察。Flowmon 将 Nette PHP 框架用于其 Web 应用程序。 未经身份验证的路由 我们开始在“AllowedModulesDecider.php”文件中枚举未经身份验证的端点,这是一个描…

1.pytest基础知识(默认的测试用例的规则以及基础应用)

一、pytest单元测试框架 1&#xff09;什么是单元测试框架 单元测试是指再软件开发当中&#xff0c;针对软件的最小单位&#xff08;函数&#xff0c;方法&#xff09;进行正确性的检查测试。 2&#xff09;单元测试框架 java&#xff1a;junit和testing python&#xff1a;un…

arcgisPro地理配准

1、添加图像 2、在【影像】选项卡中&#xff0c;点击【地理配准】 3、 点击添加控制点 4、选择影像左上角格点&#xff0c;然后右击填入目标点的投影坐标 5、依次输入四个格角点的坐标 6、点击【变换】按钮&#xff0c;选择【一阶多项式&#xff08;仿射&#xff09;】变换 7…

基于SpringBoot+定时任务实现地图上绘制车辆实时运动轨迹图

目录 1. 项目结构 2. Maven依赖配置 (pom.xml) 3. 实现后端服务 4. 配置文件 (application.properties) 5. 启动项目 6. 访问页面 实现基于北斗卫星的车辆定位和轨迹图的Maven工程&#xff08;使用模拟数据&#xff09;&#xff0c;我们将使用以下技术&#xff1a; Spri…

使用c#制作一个小型桌面程序

封装dll 首先使用visual stdio 创建Dll新项目,然后属性管理器导入自己的工程属性表&#xff08;如果没有可以参考visual stdio 如何配置opencv等其他环境&#xff09; 创建完成后 系统会自动生成一些文件&#xff0c;其中 pch.cpp 先不要修改&#xff0c;pch.h中先导入自己需…

蓝牙模块—BLE-CC41-A

1. 蓝牙的特点 蓝牙模块采用的 TI 公司设计的 CC2541芯片&#xff0c;主要面向低功耗蓝牙通信方案&#xff0c;该模块的工作频段为 2.4Ghz&#xff0c;这个频段属于国际通用频段 注意&#xff1a;蓝牙集成了一个状态指示灯&#xff0c;LED灯如果均匀慢速闪烁&#xff0c;就表示…