当前位置: 首页 > news >正文

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();}}}
}

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 目前主流语言比较
  • Alluxio EnterpriseAI on K8s 部署教程
  • 探索 Python 的火焰:Fire 库的神秘力量
  • 2016年国赛高教杯数学建模A题系泊系统的设计解题全过程文档及程序
  • 前端开发——(1)使用vercel进行网页开发
  • 标准库标头 <bit>(C++20)学习
  • 【在Linux世界中追寻伟大的One Piece】NAT|代理服务|内网穿透你会吗?
  • 从零开始学习Linux(14)---线程池
  • python有main函数吗
  • 后端-navicat查找语句(单表与多表)
  • NLP 文本匹配任务核心梳理
  • 基于51单片机的汽车倒车防撞报警器系统
  • 【SpinalHDL】Scala编程之伴生对象
  • 《C++移动语义:解锁复杂数据结构的高效之道》
  • 『功能项目』QFrameWork更新道具图片UGUI【71】
  • 〔开发系列〕一次关于小程序开发的深度总结
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • CentOS7 安装JDK
  • CSS中外联样式表代表的含义
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • Javascript Math对象和Date对象常用方法详解
  • javascript 哈希表
  • Kibana配置logstash,报表一体化
  • leetcode-27. Remove Element
  • Odoo domain写法及运用
  • Python_OOP
  • Redis的resp协议
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 大快搜索数据爬虫技术实例安装教学篇
  • 对象管理器(defineProperty)学习笔记
  • 猴子数据域名防封接口降低小说被封的风险
  • 回顾2016
  • 前端技术周刊 2019-02-11 Serverless
  • 前端相关框架总和
  • 树莓派 - 使用须知
  • 新书推荐|Windows黑客编程技术详解
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 说说我为什么看好Spring Cloud Alibaba
  • # 计算机视觉入门
  • #07【面试问题整理】嵌入式软件工程师
  • (1)无线电失控保护(二)
  • (TipsTricks)用客户端模板精简JavaScript代码
  • (备份) esp32 GPIO
  • (二)构建dubbo分布式平台-平台功能导图
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (十八)三元表达式和列表解析
  • (十六)一篇文章学会Java的常用API
  • (循环依赖问题)学习spring的第九天
  • (已解决)什么是vue导航守卫
  • (转)视频码率,帧率和分辨率的联系与区别
  • (转载)从 Java 代码到 Java 堆
  • .form文件_一篇文章学会文件上传