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 ...

随机推荐

  1. asp.net 可视化操作(一)——asp.net安装与使用

    目录 安装 创建网页 设计网页 运行 vs 2019安装asp.net 1.安装 打开vs,选择继续但无需代码 -->工具–>获取工具和功能 勾选如下选项后,点击关闭 点击更新等待安装完成 ...

  2. s函数

    Matlab 中S-函数模板翻译 10.0 基础知识 (1)Simulink仿真过程 Simulnk仿真分为两步:初始化.仿真循环.仿真是由求解器控制的,求解器主要作用是:计算模块输出.更新模块离散状 ...

  3. 洋桃电子之STM32

    1.ARM内核与分类 作者:知乎用户链接:https://www.zhihu.com/question/52915983/answer/258507276来源:知乎著作权归作者所有.商业转载请联系作者 ...

  4. 【Matlab】简单的滑模控制程序及Simulink仿真

    文章: [控制理论]滑模控制最强解析 滑模控制程序及Simulink仿真 这篇文章仿真和输出U的推到有些问题,博主根据此篇文章进行修改进行对sin(t)曲线的追踪(使用滑模控制) 使用滑模控制对sin ...

  5. python-产生每位数字相同的n位数

    读入2个正整数A和B,1<=A<=9, 1<=B<=10,产生数字AA...A,一共B个A 输入格式: 在一行中输入A和B. 输出格式: 在一行中输出整数AA...A,一共B个 ...

  6. 关于20组---三重奏的meet的评价

    meet这一软件是一款交友软件,新版本完善了以前版本的各种不足,而且能够通过手机号发验证码来创建新账户,功能多样,可以在星球.广场找到自己感兴趣的人,基本满足的交友需求. 但有一点不足之处,就是缺少创 ...

  7. 获取MCCMNC号

    public static boolean isColombiaSpanishSimCard(){        TelephonyManager telManager = (TelephonyMan ...

  8. java中final变量的用法

    4.4 final变量    final变量的数值不能在初始化之后进行改变(你希望a=3,有很多用到a的场合, 你当然不能在程序中就用3来代替a). 比如: final int h = 0; 想像有一 ...

  9. Unknown host mirrors.opencas.cn You may need to adjust the proxy settings in Gradle 报错及解决办法

    亲测Unknown host mirrors.opencas.cn You may need to adjust the proxy settings in Gradle 解决办法 - 程序员大本营 ...

  10. 小程序生成海报demo

    效果图: <view class='poste_box' id='canvas-container' style="margin:0 auto;border-radius:16rpx; ...