当前位置: 首页 > news >正文

SpringBoot+Redis+RabbitMQ完成增删改查

各部分分工职责

RabbitMQ负责添加、修改、删除的异步操作
Redis负责数据的缓存

RabbitMQ里面角色职责简单描述

RabbitMQ里面有几个角色要先分清以及他们的对应关系:

交换机、队列、路由键
交换机和队列是一对多
队列和路由键是多对多

然后就是消息的发送者(生产者)和消息的接受者(消费者)

此案例中,添加修改删除要从生产者发送到消费者,也就是说,消费者才是具体干活的角色,消息生产者只需要把消息发送到对应的队列中,由交换机根据路由键发送到对应的队列中

Redis职责简单描述

Redis只需要把要看的数据以及新添加的数据,添加到缓冲中即可,如果缓冲中没有,就从数据库查,再添加到缓存中,所以此次数据类型用的Hash

pom.xml文件坐标引入

        <!-- redis工具 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- JSON工具 https://mvnrepository.com/artifact/com.alibaba/fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><!--spring2.X集成redis所需common-pool2--><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId><version>2.6.0</version></dependency><!-- Spring Boot Starter AMQP --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>

SpringBoot的配置文件

# RabbitMQ:配置,服务器地址,端口,用户名,密码
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest# 使用 Redis 作为缓存存储,具体配置:服务器地址,端口,密码
spring.cache.type=redis
spring.redis.host=127.0.0.1
spring.redis.port=6379
#spring.redis.password=root
spring.redis.password=
# 连接工厂使用的数据库索引,redis默认有16个db,索引0-15
spring.redis.database=0
#spring.redis.timeout=0
# 连接池最大连接数(使用负值表示没有限制) 这个值决定了同时可以有多少个活动的连接
spring.redis.lettuce.pool.max-active=8
## 连接池最大阻塞等待时间(-1表示没有限制) 当连接池中的所有连接都被占用时,新的请求会等待一段时间
spring.redis.lettuce.pool.max-wait=-1
## 连接池中的最大空闲连接,连接池中最多可以有多少个空闲的连接
spring.redis.lettuce.pool.max-idle=8
## 连接池中的最小空闲连接,连接池中至少要有多少个空闲的连接
spring.redis.lettuce.pool.min-idle=0

Redis配置类

@EnableCaching      //开启缓存
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);// 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 Redis 的值(Value)GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();// 使用 StringRedisSerializer 来序列化和反序列化 Redis 的键(Key)StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();// 设置键(key)的序列化器template.setKeySerializer(stringRedisSerializer);// 设置值(value)的序列化器template.setValueSerializer(jackson2JsonRedisSerializer);// 设置 Hash 键(key)的序列化器template.setHashKeySerializer(stringRedisSerializer);// 设置 Hash 值(value)的序列化器template.setHashValueSerializer(jackson2JsonRedisSerializer);template.afterPropertiesSet();return template;}@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisSerializer<String> redisSerializer = new StringRedisSerializer();Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);//解决查询缓存转换异常的问题ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);// 配置序列化(解决乱码的问题),过期时间600秒RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(600))  //设置数据过期时间600秒.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).disableCachingNullValues();RedisCacheManager cacheManager = RedisCacheManager.builder(factory).cacheDefaults(config).build();return cacheManager;}
}

RabbitMQ配置类

如果没有配置logback,就把log.info()的代码全部删了,不影响运行,后面有的话也都删了

@Configuration
public class RabbitMQConfig {public static final String EXCHANGE_NAME = "bill.exchange"; // 交换机名称public static final String QUEUE_SAVE_UPDATE = "bill.saveupdate"; // 保存修改队列public static final String QUEUE_DELETE = "bill.delete"; // 删除队列public static final String ROUTING_SAVE_UPDATE_KEY = "bill.saveupdatekey"; // 保存修改路由键public static final String ROUTING_DELETE_KEY = "bill.deletekey"; // 删除路由键/*** 添加/修改定义队列* @return 队列对象*/@Beanpublic Queue queueSaveUpdate() {log.info(QUEUE_SAVE_UPDATE + ":RabbitMQ队列初始化成功:" + LocalDateTime.now());return new Queue(QUEUE_SAVE_UPDATE, true); // durable: 是否持久化}/*** 删除定义队列* @return 队列对象*/@Beanpublic Queue queueDelete() {log.info(QUEUE_DELETE + ":RabbitMQ队列初始化成功:" + LocalDateTime.now());return new Queue(QUEUE_DELETE, true); // durable: 是否持久化}/*** 定义交换机* @return 交换机对象*/@Beanpublic TopicExchange exchange() {log.info(EXCHANGE_NAME + ":RabbitMQ交换机初始化成功:" + LocalDateTime.now());return new TopicExchange(EXCHANGE_NAME);}/*** 绑定队列和交换机* @return 绑定对象*/@Beanpublic Binding bindingSaveUpdate() {log.info(ROUTING_SAVE_UPDATE_KEY + ":RabbitMQ绑定队列和交换机成功:" + LocalDateTime.now());return BindingBuilder.bind(queueSaveUpdate()).to(exchange()).with(ROUTING_SAVE_UPDATE_KEY);}/*** 绑定队列和交换机* @return 绑定对象*/@Beanpublic Binding bindingDelete() {log.info(ROUTING_DELETE_KEY + ":RabbitMQ绑定队列和交换机成功:" + LocalDateTime.now());return BindingBuilder.bind(queueDelete()).to(exchange()).with(ROUTING_DELETE_KEY);}
}

RabbitMQ配置消息发送者(生产者)

也就是说,在需要异步调用的地方,注入BillMessageSender,然后,调对应的方法就可以了

@Service
public class BillMessageSender {@Autowiredprivate RabbitTemplate rabbitTemplate;/*** 发送用户添加修改消息* @param bill 参数对象*/public void sendBillSaveUpdateMessage(Bill bill) {rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME, RabbitMQConfig.ROUTING_SAVE_UPDATE_KEY, bill);}/*** 发送用户删除消息* @param ids 参数列表*/public void sendBillDeleteMessage(List<Long> ids) {rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE_NAME, RabbitMQConfig.ROUTING_DELETE_KEY, ids);}
}

异步发送消息

这是在Service层,
所以把ApiResult()这个自定义返回类换成你们的就行了
ObjectMapper这个工具主要是用来处理JSON数据的,这里我用是因为为了方便实体类和Map之间相互转换的,BillMapper是我自己用到的,这个可以换成你们自己的,不影响,剩下的就基本上没啥了,有不懂的可以评论区问,看到会回复

@Slf4j
@Service
public class BillRedisService {@Resourceprivate BillMapper billMapper;@Resourceprivate ObjectMapper objectMapper;@Resourceprivate BillMessageSender billMessageSender;@Resourceprivate RedisTemplate<String, Object> redisTemplate;// redis 中 bill的键private static final String BILL_REDIS_KEY = "bill:info";/*** 保存或者修改信息* @param bill* @return*/@Transactionalpublic ApiResult saveUpdateByRedis(Bill bill){if(bill.getId() == null){billMessageSender.sendBillSaveUpdateMessage(bill);   //把要添加的信息放入消息队列}else {log.info("[ " + bill.getId() + " ] 修改缓存中的数据");String key = BILL_REDIS_KEY + bill.getId();          //找到要修改值对应的redis的keyMap map = objectMapper.convertValue(bill, Map.class);//把对象转换成mapredisTemplate.opsForHash().putAll(key, map);         //更新数据到缓存中billMessageSender.sendBillSaveUpdateMessage(bill);   //把要修改的信息放入消息队列}return ApiResult.success();}/*** 从缓存取数据* @param id* @return*/@Transactionalpublic Bill selectPrimaryKeyByRedis(Long id){Bill bill;String key = BILL_REDIS_KEY + id;//有这个键就取数据,不然就查数据库if (redisTemplate.hasKey(key)) {log.info("[ " + id + " ] 从缓存中取数据");Map<Object, Object> map = redisTemplate.opsForHash().entries(key);bill = objectMapper.convertValue(map, Bill.class);}else{log.info("[ " + id + " ] 缓存中没有,向数据库中查询数据");bill = billMapper.selectByPrimaryKey(id);String putKey = BILL_REDIS_KEY + bill.getId();          //找到要修改值对应的redis的keyMap map = objectMapper.convertValue(bill, Map.class);   //把对象转换成mapredisTemplate.opsForHash().putAll(putKey, map);         //更新数据到缓存中}return bill;}/*** 删除方法* @param ids* @return*/@Transactionalpublic ApiResult delByRedis(List<Long> ids) {log.info("[ " + Arrays.toString(ids.toArray()) + " ] 以上数据要被删除");for (Long id : ids) {String key = BILL_REDIS_KEY + id;redisTemplate.delete(key);  //删除缓存中的数据}//数据库信息交给消息队列删除billMessageSender.sendBillDeleteMessage(ids);return ApiResult.success();}
}

RabbitMQ配置消息接收者(消费者)

添加上这个注解@RabbitListener(queues = RabbitMQConfig.QUEUE_SAVE_UPDATE),
并指明监听的队列queues = RabbitMQConfig.QUEUE_SAVE_UPDATE
就能获取到消息发送者发送过来的任务以及任务参数了,就可以在这里写处理逻辑了,如果没有配置logback,可以把@Slf4j,以及log.info(),这两个代码删除了

@Slf4j
@Component
public class BillMessageReceiver {@Autowiredprivate BillMapper billMapper;@Autowiredprivate ObjectMapper objectMapper;@Resourceprivate RedisTemplate<String, Object> redisTemplate;// redis 中 bill的键private static final String BILL_REDIS_KEY = "bill:info";/*** 处理添加和修改操作* @param bill 参数对象*/@Transactional@RabbitListener(queues = RabbitMQConfig.QUEUE_SAVE_UPDATE)public void receiveBillSaveUpdateMessage(Bill bill) {log.info(RabbitMQConfig.QUEUE_SAVE_UPDATE + " 队列获取到数据:" + bill.toString());if (bill == null) {return;}if (bill.getId() == null) {bill.setDeleted(0);bill.setCreateTime(new Date());billMapper.insertSelective(bill);} else {bill.setUpdateTime(new Date());billMapper.updateByPrimaryKeySelective(bill);}String key = BILL_REDIS_KEY + bill.getId();          //添加后就有主键了,拼接成redis的keyMap map = objectMapper.convertValue(bill, Map.class);//把对象转换成mapredisTemplate.opsForHash().putAll(key, map);         //把添加的数据放到缓存中}/*** 删除数据* @param ids 参数列表*/@Transactional@RabbitListener(queues = RabbitMQConfig.QUEUE_DELETE)public void receiveBillDeleteMessage(List<Long> ids) {log.info(RabbitMQConfig.QUEUE_DELETE + " 队列获取到数据:" + Arrays.toString(ids.toArray()));Bill bill = new Bill();bill.setDeleted(1);Example example = new Example(Bill.class);Example.Criteria criteria = example.createCriteria();criteria.andIn("id",ids);billMapper.updateByExampleSelective(bill,example);}}

总结

再把逻辑捋一下

添加修改删除,这些操作统一发送给RabbitMQ,由RabbitMQ的消费者处理后续操作

查看详情,添加和更新的数据,交给Redis缓存,缓存没有,就查数据库,然后再缓存到Redis中,就第一遍查数据库,后续走的都是缓存

以上代码实现的功能就是,

全部数据查询还是走的数据库(数据量不多),但是单个查询,查询详情,先查缓存,缓存没有再查数据库,然后再添加到缓存中,下次查询就不走数据库了

添加修改删除统一发送给RabbitMQ消息队列,由消息队列异步完成后续的任务,并更新或者删除对应的缓存

这比之前单独的对数据库操作,多了2层逻辑,RabbitMQ和缓存的处理,这个例子就是简单的使用RabbitMQ和Redis,算是个小入门,如果有其他好的建议,可以评论一下,十分感谢!

相关文章:

SpringBoot+Redis+RabbitMQ完成增删改查

各部分分工职责 RabbitMQ负责添加、修改、删除的异步操作 Redis负责数据的缓存 RabbitMQ里面角色职责简单描述 RabbitMQ里面有几个角色要先分清以及他们的对应关系&#xff1a; 交换机、队列、路由键 交换机和队列是一对多 队列和路由键是多对多 然后就是消息的发送者&…...

【系统集成中级】线上直播平台开发项目质量管理案例分析

【系统集成中级】线上直播平台开发项目质量管理案例分析 一、案例二、小林在项目质量管理中存在的问题&#xff08;一&#xff09;计划阶段缺失&#xff08;二&#xff09;测试用例编制与执行问题&#xff08;三&#xff09;质量管理流程问题&#xff08;四&#xff09;质量保证…...

浪潮信息领航边缘计算,推动AI与各行业深度融合

在9月20日于安徽盛大召开的浪潮信息边缘计算合作伙伴大会上&#xff0c;浪潮信息指出&#xff0c;未来的计算领域将全面融入AI技术&#xff0c;特别是在企业边缘侧&#xff0c;智能应用特别是生成式人工智能应用正在迅速普及&#xff0c;这一趋势正引领边缘计算向边缘智算的方向…...

Koa2项目实战3 (koa-body,用于处理 HTTP 请求中的请求体)

以用户注册接口为例&#xff0c;需要在请求里携带2个参数&#xff1a;用户名&#xff08;user_name&#xff09;和密码&#xff08;password&#xff09;。 开发者需要在接口端&#xff0c;解析出user_name 、password。 在使用Koa开发的接口中&#xff0c;如何解析出请求携带…...

复盘20241012

1、 classpath "com.android.tools.build:gradle:8.5.1" 的版本 与distributionUrlhttps\://services.gradle.org/distributions/gradle-8.9-bin.zip的对应规则&#xff1a; Execution failed for task :app:compileDebugKotlin. 解决方案 切换 setting --> ot…...

泊松流负载均衡控制

目录 泊松流负载均衡控制 一、到达率λ 二、服务率μ 三、泊松流负载均衡控制 泊松流负载均衡控制 在探讨泊松流负载均衡控制时,我们主要关注的是到达率λ和服务率μ这两个核心参数。以下是对这两个参数及其在泊松流负载均衡控制中作用的详细解释: 一、到达率λ 定义:…...

3D打印矫形器市场报告:未来几年年复合增长率CAGR为10.8%

3D 打印矫形器是指使用 3D 打印技术制作的定制外部支撑装置。它们有助于稳定、引导、缓解或纠正肌肉骨骼状况&#xff0c;并根据个体患者的解剖结构进行设计&#xff0c;通常使用 3D 扫描和建模技术。3D 打印在矫形器方面的主要优势是能够生产精确适合患者解剖结构的定制装置&a…...

Richtek立锜科技线性稳压器 (LDO) 选型

一、什么是LDO? LDO也可称为低压差线性稳压器&#xff0c;适合从较高的输入电压转换成较低输出电压的应用&#xff0c;这种应用的功率消耗通常不是很大&#xff0c;尤其适用于要求低杂讯、低电流和输入、输出电压差很小的应用环境。 二、LDO的特性 LDO透过控制线性区调整管…...

Leetcode 前 k 个高频元素

使用最小堆算法来解决这道题目&#xff1a;相当于有一个容量固定为K的教室&#xff0c;只能容纳 K 个人&#xff0c;学生们逐个逐个进入该教室&#xff0c;当教室容量达到K人之后&#xff0c;每次进入一个新的学生后&#xff0c;我们将分数最低的学生(类似本题中的频率最低元素…...

[LeetCode] 面试题01.02 判定是否互为字符重拍

题目描述&#xff1a; 给定两个由小写字母组成的字符串 s1 和 s2&#xff0c;请编写一个程序&#xff0c;确定其中一个字符串的字符重新排列后&#xff0c;能否变成另一个字符串。 示例 1&#xff1a; 输入: s1 "abc", s2 "bca" 输出: true 示例 2&am…...

数据结构-4.5.KMP算法(旧版上)-朴素模式匹配算法的优化

朴素模式匹配算法最坏的情况&#xff1a; 一.实例&#xff1a; 第一轮匹配失败&#xff0c;开始下一轮的匹配&#xff1a; 不断的操作&#xff0c;最终匹配成功&#xff1a; 如上述图片所述&#xff0c;朴素模式匹配算法会导致时间开销增加&#xff0c; 优化思路&#xff1a;主…...

STM32 QSPI接口驱动GD/W25Qxx配置简要

STM32 QSPI接口GD/W25Qxx配置简要 &#x1f4dd;本篇会具体涉及介绍Winbond&#xff08;华邦&#xff09;和GD(兆易创新) NOR flash相关型号指令差异。由于网络上可以搜索到很多相关QSPI相关知识内容&#xff0c;不对QSPI通讯协议做深度解析。 &#x1f516;首先确保所使用的ST…...

UCI-HAR数据集深度剖析:训练仿真与可视化解读

在本篇文章中&#xff0c;我们将深入探讨如何使用Python对UCI人类活动识别&#xff08;HAR&#xff09;数据集进行分割和预处理&#xff0c;以及运用模型网络CNN对数据集进行训练仿真和可视化解读。 一、UCI-HAR数据集分析及介绍 UCI-HAR数据集是一个公开的数据集&#xff0c…...

牛客SQL练习详解 06:综合练习

牛客SQL练习详解 06&#xff1a;综合练习 SQL34 统计复旦用户8月练题情况SQL35 浙大不同难度题目的正确率SQL39 21年8月份练题总数 叮嘟&#xff01;这里是小啊呜的学习课程资料整理。好记性不如烂笔头&#xff0c;今天也是努力进步的一天。一起加油进阶吧&#xff01; SQL34 统…...

k8s apiserver高可用方案

目前官方推荐有 2 种方式部署k8s apiserver 高可用 keepalived and haproxy 部署有2种方式&#xff0c;一种是systemd管理的&#xff0c;另一种是pod形式&#xff0c;使用那种可以根据实际情况选择 服务部署 systemd方式 可以通过包管理工具安装&#xff0c;正常启动之后&…...

服务器数据恢复—硬盘坏扇区导致Linux系统服务器数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 一台linux操作系统网站服务器&#xff0c;该服务器上部署了几十个网站&#xff0c;使用一块SATA硬盘。 服务器故障&原因&#xff1a; 服务器在工作过程中突然宕机。管理员尝试重新启动服务器失败&#xff0c;于是将服务器上的硬盘拆下检测…...

【多线程】多线程(12):多线程环境下使用哈希表

【多线程环境下使用哈希表&#xff08;重点掌握&#xff09;】 可以使用类&#xff1a;“ConcurrentHashMap” ★ConcurrentHashMap对比HashMap和Hashtable的优化点 1.优化了锁的粒度【最核心】 //Hashtable的加锁&#xff0c;就是直接给put&#xff0c;get等方法加上synch…...

轻量服务器和云服务器ecs哪个好用一些?

轻量服务器和云服务器ecs哪个好用一些&#xff1f;轻量服务器与云服务器ECS在多方面存在显著差异&#xff0c;对于需要高性能计算和大规模数据处理的用户来说&#xff0c;ECS可能是更好的选择&#xff1b;而对于预算有限且需求较为简单的用户来说&#xff0c;轻量服务器可能更为…...

【交通标志识别系统】Python+卷积神经网络算法+人工智能+深度学习+机器学习+算法模型

一、介绍 交通标志识别系统。本系统使用Python作为主要编程语言&#xff0c;在交通标志图像识别功能实现中&#xff0c;基于TensorFlow搭建卷积神经网络算法模型&#xff0c;通过对收集到的58种常见的交通标志图像作为数据集&#xff0c;进行迭代训练最后得到一个识别精度较高…...

特种设备作业叉车司机试题附答案

1.发生事故要本着"&#xff08; &#xff09;不放过"的原则,查明原因、分清责任、严肃处理。 A.三 B.四 C.五 答案:B 2.柴油发动机在压缩行程终了时气体的温度和压力都比汽油机&#xff08; &#xff09;。 A.低 B.高 C.相同 答案:B 3.柴油发动机的压缩比比汽…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...