Redisson批量操作类RBuckets和管道利器RBatch
- 《Spring Boot 整合Redisson配置篇》
- 《Spring Boot 整合Redisson操作Redis基础篇》
- 《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的更多相关文章
- 模块(类)之间解耦利器:EventPublishSubscribeUtils 事件发布订阅工具类
如果熟悉C#语言的小伙伴们一般都会知道委托.事件的好处,只需在某个类中提前定义好公开的委托或事件(委托的特殊表现形式)变量,然后在其它类中就可以很随意的订阅该委托或事件,当委托或事件被触发执行时,会自 ...
- ASP.NET Web API 管道模型
ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是 ...
- 在.NET中使用管道将输出流转换为输入流
最近在写一段代码,将本地文件压缩加密后发送到服务器,发送到服务器的类用一个输入流作为参数获取要上传的数据,而压缩类和加密类都是输出流. 如何将输出流转换为输入流,最直观的方法是缓存输出流的全部内容到内 ...
- 管道Pipe
管道Pipe java.nio.channels包中含有一个名为Pipe(管道)的类.广义上讲,管道就是一个用来在两个实体之间单向传输数据的导管.管道的概念对于Unix(和类Unix)操作系统的用户来 ...
- JAVA IO之管道流总结大全(转)
要在文本框中显示控制台输出,我们必须用某种方法“截取”控制台流.换句话说,我们要有一种高效地读取写入到System.out和 System.err 所有内容的方法.如果你熟悉Java的管道流Piped ...
- pipe管道
回顾: 进程间通信方式: 信号,管道 消息队列,共享内存,信号量 sokcet 信号: 本质就是软中断 signal(信号,函数指针); void func(int); kill(pid,signo) ...
- 【mongoDB查询进阶】聚合管道(二) -- 阶段操作符
https://segmentfault.com/a/1190000010826809 什么是管道操作符(Aggregation Pipeline Operators) mongoDB有4类操作符用于 ...
- java IO类简单介绍
一.流的概念 流是字节序列的抽象概念.流和文件的差别:文件是数据的静态存储形式,而流是指数据传输时的形态.文件只是流的操作对象之一.流按其操作的对象不同可以分为文件流.网络流.内存流.磁带流等.Jav ...
- springboot 整合redisson
整合代码已经过测试 1.pom <!-- redisson --> <dependency> <groupId>org.redisson</groupId&g ...
随机推荐
- asp.net 可视化操作(一)——asp.net安装与使用
目录 安装 创建网页 设计网页 运行 vs 2019安装asp.net 1.安装 打开vs,选择继续但无需代码 -->工具–>获取工具和功能 勾选如下选项后,点击关闭 点击更新等待安装完成 ...
- s函数
Matlab 中S-函数模板翻译 10.0 基础知识 (1)Simulink仿真过程 Simulnk仿真分为两步:初始化.仿真循环.仿真是由求解器控制的,求解器主要作用是:计算模块输出.更新模块离散状 ...
- 洋桃电子之STM32
1.ARM内核与分类 作者:知乎用户链接:https://www.zhihu.com/question/52915983/answer/258507276来源:知乎著作权归作者所有.商业转载请联系作者 ...
- 【Matlab】简单的滑模控制程序及Simulink仿真
文章: [控制理论]滑模控制最强解析 滑模控制程序及Simulink仿真 这篇文章仿真和输出U的推到有些问题,博主根据此篇文章进行修改进行对sin(t)曲线的追踪(使用滑模控制) 使用滑模控制对sin ...
- python-产生每位数字相同的n位数
读入2个正整数A和B,1<=A<=9, 1<=B<=10,产生数字AA...A,一共B个A 输入格式: 在一行中输入A和B. 输出格式: 在一行中输出整数AA...A,一共B个 ...
- 关于20组---三重奏的meet的评价
meet这一软件是一款交友软件,新版本完善了以前版本的各种不足,而且能够通过手机号发验证码来创建新账户,功能多样,可以在星球.广场找到自己感兴趣的人,基本满足的交友需求. 但有一点不足之处,就是缺少创 ...
- 获取MCCMNC号
public static boolean isColombiaSpanishSimCard(){ TelephonyManager telManager = (TelephonyMan ...
- java中final变量的用法
4.4 final变量 final变量的数值不能在初始化之后进行改变(你希望a=3,有很多用到a的场合, 你当然不能在程序中就用3来代替a). 比如: final int h = 0; 想像有一 ...
- 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 解决办法 - 程序员大本营 ...
- 小程序生成海报demo
效果图: <view class='poste_box' id='canvas-container' style="margin:0 auto;border-radius:16rpx; ...