Redisson 总结

news2024/11/13 22:32:16

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.1
      password: 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;

    @Autowired
    public 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 {

    @Bean
    public 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 {

    @Serial
    private 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;

    @Autowired
    public 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;

    @Autowired
    public 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;

    @Autowired
    public 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> {

    @Serial
    private static final long serialVersionUID = -8862397425409851538L;

    private Long id;

    private String title;

    private String content;

    @Override
    public 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;

    @Autowired
    public 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;

    @Autowired
    public 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;

    @Autowired
    public 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;

    @Autowired
    public DemoController(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @GetMapping("/test")
    public void test() {
        RBloomFilter<String> rBloomFilter = redissonClient.getBloomFilter("test");
        // 初始化预期插入的数据量为10000和期望误差率为0.01
        rBloomFilter.tryInit(10000, 0.01);
        // 插入部分数据
        rBloomFilter.add("100");
        rBloomFilter.add("200");
        rBloomFilter.add("300");
        // 设置过期时间
        rBloomFilter.expire(Duration.ofSeconds(30));
        // 判断是否存在
        System.out.println(rBloomFilter.contains("300")); // true
        System.out.println(rBloomFilter.contains("200")); // true
        System.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;

    @Autowired
    public 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;

    @Autowired
    public 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;

    @Autowired
    public 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;

    @Autowired
    public 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.coloradmin.cn/o/2155061.html

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

相关文章

掌控历史:如何通过Git版本管理工具提升你的开发效率

先一览全局: git目录 一.打开git二.git bash的基础命令三.配置git四.仓库搭建五.文件操作和状态六.忽略文件七.gitee的使用1.添加公钥2.创建仓库 八.vs中使用git九.git分支常用命令十.文件差异比较十一.文件回溯和推进十二.合并冲突和消除十三.合并/压缩提交十四.远程仓库推拉十…

SkyWalking 环境搭建部署

架构简介 skywalking agent : 和业务系统绑定在一起,负责收集各种监控数据skywalking oapservice : 是负责处理监控数据的,比如接受skywalking agent的监控数据,并存储在数据库中;接受skywalking webapp的前端请求,从数据库查询数据,并返回数据给前端。Skywalking oapserv…

第一个Web项目(java+servlet+jsp)

通过百度网盘分享的文件&#xff1a;第一个Web项目 链接&#xff1a;https://pan.baidu.com/s/11vnAPeAf6Dtax7H6aYKZgA 提取码&#xff1a;1234 目录 声明&#xff1a; 简介&#xff1a; 注意&#xff1a; 操作步骤&#xff1a; 1.在idea中新建java项目&#xff0c;项目…

华为HarmonyOS地图服务 7- 在地图上绘制标记

场景介绍 本章节将向您介绍如何在地图的指定位置添加标记以标识位置、商家、建筑等。 点标记用来在地图上标记任何位置&#xff0c;例如用户位置、车辆位置、店铺位置等一切带有位置属性的事物。Map Kit提供的点标记功能&#xff08;又称 Marker&#xff09;封装了大量的触发…

TMS320F28335的定时器中断实验

TTMS320F28335 的 CPU 定时器有 3 个且均为 32 位,分别是 Timer0、Timer1、Timer2, 其中 Timer2 是为操作系统 DSP/BIOS 保留的,当未移植操作系统时,可用来做普 通的定时器。这三个定时器的中断信号分别为 TINT0,TINT1,TINT2,分别对应中断向量于 INT1,INT13,INT14。 1 …

C++速通LeetCode中等第15题-搜索二维矩阵II(两种方法)

方法一&#xff1a;二分法按行遍历查找&#xff1a; class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {for (const auto& row: matrix) {auto it lower_bound(row.begin(), row.end(), target);if (it ! row.end()…

苹果macOS 15.0 Sequoia正式版发布:iPhone应用镜像玩、手机消息电脑知

9月17日苹果向 Mac 电脑用户推送了 macOS 15 更新&#xff08;内部版本号&#xff1a;24A335&#xff09;&#xff0c;除了引入数个 iOS 18 的新功能外&#xff0c;macOS 15 Sequoia 还带来了全新的 Continuity 功能 ——iPhone 镜像。 iPhone 镜像功能可以让用户直接在 Mac 上…

高密原型验证系统解决方案(上篇)

0 引言 随着当今 SoC 设计规模的快速膨胀&#xff0c;仅仅靠几 颗当代最先进的 FPGA 已经无法满足原型验证的需求。简单的增加系统的容量&#xff0c;会遇到系统时钟复位同 步&#xff0c;设计分割以及高速接口和先进 Memory控制器 IP 验证等多重困难。此时&#xff0c;一个商用…

vscode软件在 C发中常用插件

一. 简介 本文简单介绍一下&#xff0c;当做 C开发时 vscode软件常用的插件。 vscode软件是 微软公司目前提供的一款免费的开发软件&#xff0c;可以通过 vscode官网下载 vscode。 二. vscode软件在 C开发中常用插件 注意&#xff1a;vscode软件安装后&#xff0c;可以直接…

表盘针头位置检测系统源码分享

表盘针头位置检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

JAVA开源项目 房屋租赁系统 计算机毕业设计

本文项目编号 T 041 &#xff0c;文末自助获取源码 \color{red}{T041&#xff0c;文末自助获取源码} T041&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…

MySQL深入原理

MySQL深入原理 索引、事务、日志原理、InnoDB引擎、缓存、锁 有4个数据库是属于MySQL自带的系统数据库&#xff1a; ​ mysql MySQL 系统自带的核心数据库&#xff0c;它存储了MySQL的用户账户和权限信息&#xff0c;一些存储过程、事件的定义信息&#xff0c;一些运行过程中…

WebGL系列教程九(动画)

目录 1 前言2 绘制立方体并进行纹理映射3 动画思路4 开始绘制4.1 在顶点着色器中声明旋转矩阵4.2 获取旋转矩阵变量并进行赋值4.3 计算角度4.4 每一帧都去绘制4.5 效果4.6 完整代码 5 总结 1 前言 上一篇我们讲了WebGL中的基础语法&#xff0c;现在我们已经讲过了三维物体的绘制…

14.面试算法-字符串常见算法题(三)

1. 字符串回文问题 1.1 LeetCode.125. 验证回文串 回文问题在链表中是重点&#xff0c;在字符串中同样是个重点。当初我去美团面试第一轮技术面的第一个算法题就是让写判断字符串回文的问题。 这个本身还是比较简单的&#xff0c;只要先转换成字符数组&#xff0c;然后使用双…

PS相关操作记录

1. 磨皮步骤 1.1. 图层操作 先对照片进行去瑕疵、液化等操作&#xff0c;操作完的图层&#xff0c;重命名为液化&#xff0c;方便识别。复制两个图层&#xff0c;分别改为“低频”、“高频”&#xff0c;低频在下&#xff0c;高频在上。选中“低频”图层&#xff0c;滤镜 -&g…

NodeJs文档

文件操作 // 1. 导入fs模块 const fs require(fs)文件写入 //异步写入 // fs.writeFile(文件名&#xff0c; 待写入的数据&#xff0c; 选项设置&#xff08;可选&#xff09;&#xff0c; 回调函数) fs.writeFile(./座右铭.txt, 三人行&#xff0c;必有我师傅, err > {/…

kubernetes应用的包管理Helm工具

目录 一、helm简介 二、部署helm 1、官网与资源 2、部署helm &#xff08;1&#xff09;安装helm &#xff08;2&#xff09;配置helm命令补齐 三、helm常用操作 &#xff08;1&#xff09;查询官方应用中心 &#xff08;2&#xff09;管理第三方repo源 &#xff08;…

AI周报(9.15-9.21)

AI应用-宇宙建筑师&#xff1a;AI探索宇宙结构 近日&#xff0c;来自马克斯普朗克研究所等机构&#xff0c;利用宇宙学和红移依赖性对宇宙结构形成进行了场级仿真。 AI版“宇宙闪电侠”&#xff1a;若以传统宇宙模拟的缓慢行进比作悠然自得的蜗牛&#xff0c;那么AI便宛如宇宙…

centos7 添加中文字体

一、打开C:\Windows\Fonts 复制 复制出来再拷贝到linux服务器目录&#xff1a;/usr/share/fonts/jtwin #执行 #mkdir /usr/share/fonts/jtwin chmod -R 755 /usr/share/fonts/jtwin yum -y install ttmkfdir ttmkfdir -e /usr/share/X11/fonts/encodings/encodings.dir 编辑&…

Ubuntu 安装和使用 Fcitx 中文输入法;截图软件flameshot

一、Ubuntu 安装和使用 Fcitx 中文输入法 在 Ubuntu 上安装和使用 Fcitx 输入法框架是一个常见的选择&#xff0c;特别是对于需要中文输入的用户。以下是详细的步骤来安装和配置 Fcitx 输入法&#xff1a; 1. 安装 Fcitx 和相关输入法 首先&#xff0c;更新你的包列表并安装…