news 2026/10/19 20:13:22

Redis入门到精通(十一),Redission操作Redis

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis入门到精通(十一),Redission操作Redis

一. 初识Redission

前面我们讲了Redis的三大常见客户端中的Jedis和Lettuce,今天就跟大家聊聊这个Redisson。那Redisson是什么呢?Redisson是一个在Redis的基础上实现的Java内存数据网格(In-Memory Data Grid),它充分利用了Redis键值数据库提供的一系列优势,基于Java实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类,让使用Redis更加简单、便捷,从而让使用者能够将更多精力集中到业务逻辑处理上。

也就是说Redisson不仅仅是一个Redis客户端,它是一个以内存 Redis 服务器作为后端的处理 Java 对象,它还实现了很多具有分布式特性的常用工具类。比如分布式锁、布隆过滤器等。下图是官网提供的Redisson可以做的事情。

1.依赖

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.13.0</version> </dependency> </dependencies>

2.yml文件

spring: redis: host: 127.0.0.1 port: 6379 password: 123456

二.使用方法

1.对象存储

Redisson将Redis中的字符串数据结构封装成了RBucket,通过RedissonClient的getBucket(key)方法获取一个RBucket对象实例,通过这个实例可以设置value或设置value和有效期。并且可以操作所有类型的对象。示例如下代码。

/** * 通用对象桶,可以用来存放任类型的对象 */ @Test public void RedissonBucket(){ //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作对象桶来存储对象(同步)==================== RBucket<Object> bucket = redissonClient.getBucket("name"); //设置值为victory,过期时间为3小时 bucket.set("victory",30, TimeUnit.HOURS); Object value = bucket.get(); System.out.println(value); //通过key取value值 Object name = redissonClient.getBucket("name").get(); System.out.println(name); //====================关闭客户端==================== redissonClient.shutdown(); }

2.二进制流存储

/** * 二进制流 * 提供了InputStream接口和OutputStream接口的实现 */ @Test public void RedissonStream() throws IOException { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作流来存储对象==================== RBinaryStream stream = redissonClient.getBinaryStream("stream"); stream.set("name is ".getBytes()); OutputStream outputStream = stream.getOutputStream(); outputStream.write("victory".getBytes()); InputStream inputStream = stream.getInputStream(); ByteArrayOutputStream result = new ByteArrayOutputStream(); byte[] bytes = new byte[1024]; int length; while ((length = inputStream.read(bytes)) != -1) { result.write(bytes, 0, length); } System.out.println(result.toString()); //====================关闭客户端==================== redissonClient.shutdown(); }

3.List

/** * list * Redisson操作list */ @Test public void list() { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作list==================== RList<String> list = redissonClient.getList("list"); list.add("victory1"); list.add("victory2"); System.out.println(list); //取值 List<Object> list1 = redissonClient.getList("list").get(); System.out.println(list1); //移除索引0位置元素 list.remove(0); System.out.println(list); //通过key取value值 List<Object> list2 = redissonClient.getList("list").get(); System.out.println(list2); //====================关闭客户端==================== redissonClient.shutdown(); }

4.Set

/** * set * Redisson操作set */ @Test public void set() { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作list==================== RSet<Object> set = redissonClient.getSet("set"); set.add("victory1"); set.add("victory2"); System.out.println(set); //通过key取value值 RSet<Object> set1 = redissonClient.getSet("set"); System.out.println(set1); //====================关闭客户端==================== redissonClient.shutdown(); }

5.Map

Redisson将Redis中的字符串数据结构封装成了RMap,就是原本redis中的string类型
/** * map * Redisson操作map * Redisson将Redis中的字符串数据结构封装成了RMap,就是原本redis中的string类型 */ @Test public void map() { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作list==================== RMap<Object, Object> map = redissonClient.getMap("map"); map.put("name1","victory1"); map.put("name2","victory2"); map.forEach((key,value)->{ System.out.println("key = "+key+" ,value = "+ value); }); //通过key取value值 Object o = redissonClient.getMap("map").get("name1"); System.out.println(o); //====================关闭客户端==================== redissonClient.shutdown(); }

6.队列

这里的队列和下面要说的发布订阅的功能跟MQ的不能说是毫无关系,只能说是一毛一样,计划这个专栏结束下个专栏专门来聊MQ,欢迎个位大佬交流指正

/** * 队列 * Redisson操作queue */ @Test public void queue() { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作queue==================== RQueue<String> queue = redissonClient.getQueue("queue"); //存值 queue.add("victory1"); queue.add("victory2"); //取值 String item = queue.poll(); System.out.println(item); // RQueue<Object> queue1 = redissonClient.getQueue("queue"); System.out.println(queue1); //====================关闭客户端==================== redissonClient.shutdown(); }

7.限流器

基于Redis的分布式限流器可以用来在分布式环境下现在请求方的调用频率。既适用于不同Redisson实例下的多线程限流,也适用于相同Redisson实例下的多线程限流。该算法不保证公平性。

/** * 限流器 * Redisson操作rateLimiter */ @Test public void rateLimiter() throws InterruptedException { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作rateLimiter==================== RRateLimiter rateLimiter = redissonClient.getRateLimiter("rateLimiter"); //创建限流器,最大流速:每1秒钟产生20个令牌 rateLimiter.trySetRate(RateType.OVERALL, 20, 1, RateIntervalUnit.SECONDS); for (int i = 0; i < 10; i++) { new Thread(new Runnable() { int i = 0; @Override public void run() { while(true) { rateLimiter.acquire(1); System.out.println(Thread.currentThread() + "-" + System.currentTimeMillis() + "-" + i++); } } }).start(); } //等待执行完成,不设置等待可能出现还未执行完成客户端就关闭的情况 Thread.sleep(5000); //====================关闭客户端==================== redissonClient.shutdown(); }

8.可重入锁

/** * 可重入锁 * Redisson操作RLock */ @Test public void lock() throws InterruptedException { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作lock==================== RLock lock = redissonClient.getLock("lock"); for (int i = 0; i < 5; i++) { new Thread(() -> { lock.lock(); try { System.out.println(Thread.currentThread() + "-" + System.currentTimeMillis() + "-" + "获取了锁"); Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } }).start(); } //等待执行完成,不设置等待可能出现还未执行完成客户端就关闭的情况 Thread.sleep(5000); //====================关闭客户端==================== redissonClient.shutdown(); }

9.发布订阅

Redisson的分布式话题 RTopic 对象实现了发布、订阅的机制。

/** * 发布订阅操作 * Redisson操作RTopic执行发布订阅操作 **/ @Test public void topicPublisherAndSubscriber() throws InterruptedException { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); RedissonClient redissonClient1 = Redisson.create(config); //====================操作topic执行发布操作==================== RTopic topic1 = redissonClient.getTopic("topic",new SerializationCodec()); topic1.publish(new Message(1L,"victory",18)); //====================操作topic执行订阅操作==================== Thread.sleep(5000); RTopic topic = redissonClient1.getTopic("topic", new SerializationCodec()); topic.addListener(Message.class, new MessageListener<Message>() { @Override public void onMessage(CharSequence channel, Message msg) { System.out.println("onMessage:=========" + channel + "; Thread:========= " + Thread.currentThread().toString()); System.out.println(" name : " + msg.getName() + " age : " + msg.getAge()); LoggerFactory.getLogger(RedissonDemo.class).info("Redisson接收到消息",msg); } }); //====================关闭客户端==================== redissonClient.shutdown(); redissonClient1.shutdown(); }

10.布隆过滤器

布隆过滤器是一个非常长的二进制向量和一系列随机哈希函数的组合,可用于检索一个元素是否存在。

主要作用

应对缓存穿透等场景,如果高并发一波冷数据的情况下,大量的请求可能会击穿我们的缓存导致了雪崩,此时我们可以设置布隆过滤器,如果索引在我们的过滤器中,请求来我们先去查内存,如果内存没有再去查DB,如果索引不存在于过滤器中我们快速返回失败来提高程序的性能。

原理如下:

建立一个二进制向量,所有位设置0;
选择K个散列函数,用于对元素进行K次散列,计算向量的位下标;
添加元素:将K个散列函数作用于该元素,生成K个值作为位下标,将向量的对应位设置为1;
检索元素:将K个散列函数作用于该元素,生成K个值作为位下标,若向量的对应位都是1,则说明该元素可能存在;否则,该元素肯定不存在;

当然他也有他的局限性,比如误差率。随着存入的元素数量增加,误差率随之增加。但是如果元素数量太少,则使用散列表足矣。

/** * Redisson利用Redis实现了Java分布式布隆过滤器(Bloom Filter) * 作用:在缓存层前添加布隆过滤器,常用于高并发场景下应对缓存穿透问题 * 布隆过滤器是一个非常长的二进制向量和一系列随机哈希函数的组合,可用于检索一个元素是否存在; * */ @Test public void bloomFilter() { //====================创建Redisson客户端==================== Config config = new Config(); //config.useSingleServer().setAddress("redis://127.0.0.1:6379").setPassword("123456"); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); RedissonClient redissonClient = Redisson.create(config); //====================操作布隆过滤器==================== RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("bloom-filter"); // 初始化布隆过滤器,初始化预期插入的数据量为200,期望误差率为0.01 bloomFilter.tryInit(200, 0.01); //插入数据 bloomFilter.add("丁胜利"); bloomFilter.add("丁向前"); bloomFilter.add("胜利丁"); //判断是否包含 boolean victory = bloomFilter.contains("丁胜利"); boolean forward = bloomFilter.contains("向前丁"); System.out.println(victory); //true System.out.println(forward); //false //====================关闭客户端==================== redissonClient.shutdown(); }

三.总结

Redisson相比于之前聊过的Jedis和Lettuce来说显得过于笨重,如果只是需要Redis实现简单的热点数据缓存和登录定时过期之类的小功能的话,建议在项目中慎重使用。

到这里吧,Redisson可以做的事情还有很多,我只列举了同步操作的其中一部分就已经一万多字了,还有异步和响应式丁点都没有涉及。但是基本都大同小异,如果有理解不到的欢迎交流。

因为之前虽然用过但是从来没有这么系统的去了解每一个功能,所以导致这一块在创作的时候需要查询大量的资料,Demo的进度也是格外的慢。学然后知不足,教然后知困。各位共勉。

老规矩,需要Demo的话可评论或者私聊我,所有代码的Demo都有敲而且都会有保留,各位看官如果满意的话还请点个赞再走。下面我想想还要再补充一些集群相关的本专栏也就该结束了应该,暂时想不到还有其他什么需要补充的地方了。

参考文献

Redisson: Redis Java client with features of In-Memory Data Grid

概览 - 《Redisson 官方文档中文翻译》 - 书栈网 · BookStack

阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台

阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 7:17:21

从D4RL到NewRL:离线强化学习评估为何失真及如何构建真实场景基准

做离线强化学习研究的同学&#xff0c;这两年估计都有一个共同体感&#xff1a;在D4RL这类标准基准上刷出来的分数越来越好看&#xff0c;可一旦把模型放到真实系统里试运行&#xff0c;各种问题就冒出来了——状态观测有噪声、奖励迟迟不来、执行器还经常延迟&#xff0c;最后…

作者头像 李华
网站建设 2026/10/14 18:18:29

实时大数据平台元数据管理实战:从Schema演化到血缘追踪

实时大数据平台的元数据管理有多难&#xff1f;我这里想先抛一个场景&#xff1a;你负责的实时数仓跑了大半年&#xff0c;上游业务表某天加了个字段&#xff0c;按说这是常用操作&#xff0c;结果当天晚上实时任务大面积报错、重启&#xff0c;Kafka Topic里的数据堆积到几千万…

作者头像 李华
网站建设 2026/10/15 11:05:23

Azure Data Studio 跨平台连接 SQL Server 实战与避坑指南

简介&#xff1a;Azure Data Studio 是一款跨平台数据管理工具&#xff0c;面向数据库开发、运维及数据分析人员&#xff0c;可在 Windows、macOS 与 Linux 上统一管理 SQL Server、Azure SQL DB 与 Azure SQL DW&#xff0c;并兼容 PostgreSQL 等数据源。它解决多环境数据库连…

作者头像 李华
网站建设 2026/10/17 8:27:39

从Playwright到Allure:自动化测试报告优化与历史趋势追踪实战

前阵子帮一个项目把Playwright测试报告从默认的HTML报告换成了Allure&#xff0c;整个“跑完用例看结果”的体验完全不一样了。以前打开Playwright原生报告页面&#xff0c;看到的只是当前这一次运行的Passed/Failed列表&#xff0c;想回答“这周到底哪个模块失败率最高”“失败…

作者头像 李华
网站建设 2026/10/13 19:19:19

深入理解TypeScript联合类型与类型别名:从语法到实战避坑

先讲一个我亲身踩过的场景。当时我在维护一个数据查询接口&#xff0c;前端会把筛选条件传过来&#xff0c;早期代码把所有筛选条件当成同一种固定结构处理&#xff0c;类型定义也只写了其中一个形态。结果线上告警直接炸了&#xff0c;代码里trim()方法报了 TypeError——因为…

作者头像 李华
网站建设 2026/10/14 3:22:16

小微企业AI agent落地指南:从省几十元小成效建立信任

1. 小微企业对AI agent的信任困局与破局点1.1 为什么几十块钱的成效比技术演示更有说服力我接触过不少做小生意的人&#xff0c;开网店的、做本地服务的、搞批发零售的&#xff0c;聊到AI agent&#xff0c;他们的第一反应几乎都是同一个表情——半信半疑。你跟他说大模型多厉害…

作者头像 李华