1. Spring Boot 整合Redisson配置篇
  2. Spring Boot 整合Redisson操作Redis基础篇
  3. 《Redisson批量操作类RBuckets和管道利器RBatch》

摘要:使用Redisson的类RBuckets和RBatch批量操作Redis,减少网络请求次数。

综述

  Redis的部署方式有单节点部署、哨兵方式部署、集群方式部署3种方式,这3中方式都使用的是原生的redis。本文基于单节点部署,使用的Spring Boot版本为2.5.x

RBuckets批量操作

  在Spring Boot项目中,通过RBuckets接口实现批量操作多个RBucket对象,官方示例如下:

RBuckets buckets = redisson.getBuckets();
Map<String, V> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3");
Map<String, Object> map = new HashMap<>();
map.put("myBucket1", new MyObject());
map.put("myBucket2", new MyObject());
// 利用Redis的事务特性,同时保存所有的通用对象桶,如果任意一个通用对象桶已经存在则放弃保存其他所有数据。
buckets.trySet(map);
// 同时保存全部通用对象桶。
buckets.set(map);

  方法介绍:

  • Map<String,V> get(String... keys):返回桶的key-value对。
  • boolean trySet(Map<String,?> buckets):利用Redis的事务特性,同时保存所有的通用对象桶,如果任意一个通用对象桶已经存在则放弃保存其他所有数据。
  • void set(Map<String,?> buckets):同时保存全部通用对象桶。

RBatch 批量操作

  多个连续命令可以通过RBatch对象在一次网络会话请求里合并发送,这样省去了产生多个请求消耗的时间和资源。这在Redis中叫做管道。

  RBatch管道功能就是REDIS的批量发送,实际上是客户端的功能,与服务端无关。相当于把多个请求的命令放在一个数据包通过TCP发送到服务端,然后客户端再一次性读取所有的命令回应。管道技术最显著的优势是提高了 redis 服务的性能。

   /**
* 批量操作
*/
private void batchDemo() throws ExecutionException, InterruptedException {
Map<String, String> map = new HashMap<>();
map.put("abc", "testStr");
map.put("abcDemo", "redis");
redisUtils.setMassStrings(map); log.info("String 测试数据:{}", redisUtils.getStr("abc") + " "
+ redisUtils.getStr("abcDemo")); RBatch batch = redisUtils.createBatch();
// 模拟购物车场景,真实场景中请替换店铺ID shopId 和商品ID commodityId
String field = "shopId:commodityId";
// 把即将执⾏的命令放进 RBatch
RMapAsync testMap = batch.getMap("customerId:"+ 32L);
// 更新value,并返回上一次的值
String commodityNum = "mapValue" + String.valueOf((int)(Math.random()*9 + 100));
log.info("当前商品数量commodityNum是:{}", commodityNum);
testMap.putAsync(field, commodityNum);
testMap.putAsync("test2", "mapValue3");
testMap.putAsync("test2", "mapValue5");
testMap.putAsync("test:"+ String.valueOf((int)(Math.random()*900 + 100)), String.valueOf((int)(Math.random()*900 + 100))); RAtomicLongAsync counter = batch.getAtomicLong("counter"); RFuture<Long> num = counter.incrementAndGetAsync(); // 执行RBatch中的全部命令,并返回执行结果
BatchResult result = batch.execute();
List list = result.getResponses();
log.info("Map Batch 执行结果:{}", list);
log.info("计数器当前值:{}", num.get());
}

  执行batchDemo()后,控制台打印结果如下:

StudyRedissonController - String 测试数据:testStr redis
StudyRedissonController - 当前商品数量commodityNum是:mapValue106
StudyRedissonController - Map Batch 执行结果:[mapValue101, mapValue5, mapValue3, null, 8]
StudyRedissonController - 计数器当前值:8

  测试用例主要介绍了Hash,顺便介绍一下它的使用场景:

  • 存储结构化的数据,比如 Java 中的对象。其实 Java 中的对象也可以用 string 进行存储,只需要将对象序列化成 json 字符串就可以,但是如果这个对象的某个属性更新比较频繁的话,那么每次就需要重新将整个对象序列化存储,这样消耗开销比较大。可如果用 hash 来存储对象的每个属性,那么每次只需要更新要更新的属性就可以。
  • 购物车场景。以业务线+用户id作为key,以店铺编号+商品的id作为存储的field,以选购商品数量作为键值对的value,这样就构成了购物车的三个要素。

  在集群模式下,所有的命令会按各个槽所在的节点,筛选分配到各个节点并同时发送。每个节点返回的结果将会汇总到最终的结果列表里。上述demo中用到的工具类如下:

@Component
public class RedisUtils { private RedisUtils() {
} /**
* 默认缓存时间
*/
private static final Long DEFAULT_EXPIRED = 32000L; /**
* 自动装配redisson client对象
*/
@Resource
private RedissonClient redissonClient;
/**
* 获取getBuckets 对象
*
* @return RBuckets 对象
*/
public RBuckets getBuckets() {
return redissonClient.getBuckets();
}
/**
* 读取缓存中的字符串,永久有效
*
* @param key 缓存key
* @return 字符串
*/
public String getStr(String key) {
RBucket<String> bucket = redissonClient.getBucket(key);
return bucket.get();
} // ---------------- 批量操作 ------------------------
/**
* 获取RBatch
*
* @return RBatch
*/
public RBatch createBatch() {
return redissonClient.createBatch();
} /**
* 批量移除缓存
*
* @param keys key 对象
*/
public void deleteBatch(String... keys) {
if (null == keys) {
return;
}
this.getKeys().delete(keys);
} /**
* 批量缓存字符串,缺点:不可以设置过期时间
*
* @param map 缓存key-value
*/
public void setMassStrings(Map<String, String> map) {
if (MapUtils.isEmpty(map)) {
return;
}
RBuckets buckets = redissonClient.getBuckets();
// 同时保存全部通用对象桶。
buckets.set(map);
} /**
* 批量缓存字符串,支持过期
*
* @param map 缓存key-value
* @param leaseTime 缓存有效期,必传
*/
public void setMassStrings(Map<String, String> map, long leaseTime) {
if (MapUtils.isEmpty(map)) {
return;
}
final long expireTime = leaseTime <= 0L ? DEFAULT_EXPIRED : leaseTime;
RBatch batch = redissonClient.createBatch();
map.forEach(new BiConsumer<String, String>() {
public void accept(String key, String value) {
batch.getBucket(key).setAsync(value, expireTime, TimeUnit.SECONDS);
}
});
batch.execute();
} }

结束语

  关于redisson中如何使用批量操作类RBuckets和管道利器RBatch就分享到这里,希望本文对大家的学习或者工作具有一定的参考和学习价值;如果有疑问,大家可以在评论区留言交流,也希望大家多多点赞关注。谢谢大家对楼兰胡杨的支持!

Reference

Redisson批量操作类RBuckets和管道利器RBatch的更多相关文章

  1. 模块(类)之间解耦利器:EventPublishSubscribeUtils 事件发布订阅工具类

    如果熟悉C#语言的小伙伴们一般都会知道委托.事件的好处,只需在某个类中提前定义好公开的委托或事件(委托的特殊表现形式)变量,然后在其它类中就可以很随意的订阅该委托或事件,当委托或事件被触发执行时,会自 ...

  2. ASP.NET Web API 管道模型

    ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是 ...

  3. 在.NET中使用管道将输出流转换为输入流

    最近在写一段代码,将本地文件压缩加密后发送到服务器,发送到服务器的类用一个输入流作为参数获取要上传的数据,而压缩类和加密类都是输出流. 如何将输出流转换为输入流,最直观的方法是缓存输出流的全部内容到内 ...

  4. 管道Pipe

    管道Pipe java.nio.channels包中含有一个名为Pipe(管道)的类.广义上讲,管道就是一个用来在两个实体之间单向传输数据的导管.管道的概念对于Unix(和类Unix)操作系统的用户来 ...

  5. JAVA IO之管道流总结大全(转)

    要在文本框中显示控制台输出,我们必须用某种方法“截取”控制台流.换句话说,我们要有一种高效地读取写入到System.out和 System.err 所有内容的方法.如果你熟悉Java的管道流Piped ...

  6. pipe管道

    回顾: 进程间通信方式: 信号,管道 消息队列,共享内存,信号量 sokcet 信号: 本质就是软中断 signal(信号,函数指针); void func(int); kill(pid,signo) ...

  7. 【mongoDB查询进阶】聚合管道(二) -- 阶段操作符

    https://segmentfault.com/a/1190000010826809 什么是管道操作符(Aggregation Pipeline Operators) mongoDB有4类操作符用于 ...

  8. java IO类简单介绍

    一.流的概念 流是字节序列的抽象概念.流和文件的差别:文件是数据的静态存储形式,而流是指数据传输时的形态.文件只是流的操作对象之一.流按其操作的对象不同可以分为文件流.网络流.内存流.磁带流等.Jav ...

  9. springboot 整合redisson

    整合代码已经过测试 1.pom <!-- redisson --> <dependency> <groupId>org.redisson</groupId&g ...

  10. C# 管道式编程

    受 F# 中的管道运算符和 C# 中的 LINQ 语法,管道式编程为 C# 提供了更加灵活性的功能性编程.通过使用 扩展函数 可以将多个功能连接起来构建成一个管道. 前言 在 C# 编程中,管道式编程 ...

随机推荐

  1. 使用CoreProfiler/NanoProfiler实现跨平台&amp;应用的整合性能调试

    摘要 NanoProfiler是一个开源.NET性能调试类库,CoreProfiler是其.NET Core版本的实现.在之前的一些文章中,我曾介绍过NanoProfiler的主要使用方式,以及如何为 ...

  2. 【ASP.NET Identity系列教程(一)】ASP.NET Identity入门

    注:本文是[ASP.NET Identity系列教程]的第一篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序 ...

  3. Ubuntu 14.10 下网络流量实时监控ifstat iftop命令详解

    ifstat 介绍 ifstat工具是个网络接口监测工具,比较简单看网络流量 实例 默认使用 #ifstat eth0 eth1 KB/s in KB/s out KB/s in KB/s out 0 ...

  4. 关于JPA封装数据库数据到实体不调用属性的get和set的方法解决办法

    今天发现JPA封装数据库数据到实体并不调用属性的get和set的,郁闷,本来想在set方法做改字段的值处理的谁知道遇到这个情况: @Column(name = acode) @Access(value ...

  5. Android 面试精华题目总结

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24015867 下面的题目都是楼主在android交流群大家面试时遇到的,如果大家 ...

  6. ajax实现分页

    使用ajax分页原理:第一步:做一个表格 第二步:封装两个方法.第三步:新建个负责显示页面.第四步:做一个纯PHP处理页面处理要显示页的所有数据 首先使用一张数据比较多的数据库中的表格: 首页面加载后 ...

  7. 【12c】扩展数据类型(Extended Data Types)-- MAX_STRING_SIZE

    [12c]扩展数据类型(Extended Data Types)-- MAX_STRING_SIZE 在12c中,与早期版本相比,诸如VARCHAR2, NAVARCHAR2以及 RAW这些数据类型的 ...

  8. RAID的基本介绍

    一.传统磁盘的劣势 影响计算机性能的组件一般包括:CPU.主板总线IO.内存IO.硬盘IO.网卡IO.现代处理器性能已经很高了,但是计算机整体IO性能较弱,严重影响了计算机性能 现代的计算机总线.内存 ...

  9. PHP 传值操作和传地址操作

    PHP中有两种赋值操作 一种是传值操作 example: $a = 1; $b = $b; 这个就是传值 传地址是: example2: $a = 1; $b = &$a; 这两者有什么区别呢 ...

  10. python2.0_day20_bbs系统开发

    BBS是一个最简单的项目.在我们把本节课程的代码手敲一遍后,算是实战项目有一个入门.首先一个项目的第一步是完成表设计,在没有完成表结构设计之前,千万不要动手开发(这是老司机的忠告!)废话不多说,现在我 ...