后端杂七杂八系列篇三

后端杂七杂八系列篇三

  • ① Spring Event用法
    • ① 同步代码的用法
      • ① 自定义事件
      • ② 定义监听器
      • ③ 定义发布者
      • ④ 发布消息后,接口收到消息
    • ② 异步代码的用法
      • ① `开启异步`
      • ② 自定义事件
      • ③ 自定义监听器(推荐使用 @EventListener 注解),`使用@Async注解`
      • ④ 定义发布者
      • ⑤ 发布消息后,`观察同步与异步消息`
  • ② SpringBoot+Redis BitMap 实现签到与统计功能
    • ① 什么是Redis BitMap ?
    • ② SpringBoot 整合 Redis 实现签到 功能
      • ① 设计思路
      • ② 如何连续签到天数?
      • ③ 如何得到本月到今天为止的所有签到数据?
      • ④ 如何从后向前遍历每个Bit位?
      • ⑤ 代码Demo
  • ③ 基于Redis实现分布式锁(使用Redisson)
  • ⑤ redis 缓存穿透

① Spring Event用法

实际业务开发过程中,业务逻辑可能非常复杂,核心业务 + N个子业务。如果都放到一块儿去做,代码可能会很长,耦合度也会很高。

MQ解决这个问题,但是在业务不是特别复杂的情况下,我们可以使用观察者设计模式来完成。Spring Event(Application Event)其实就是一个观察者设计模式。

在这里插入图片描述

在这里插入图片描述


① 同步代码的用法

① 自定义事件

// 定义事件,继承 ApplicationEvent 的类成为一个事件类@Data
@ToString
public class OrderProductEvent extends ApplicationEvent {/** 该类型事件携带的信息 */private String orderId;public OrderProductEvent(Object source, String orderId) {super(source);this.orderId = orderId;}
}

② 定义监听器

// 监听并处理事件,实现 ApplicationListener 接口或者使用 @EventListener 注解@Slf4j
@Component
public class OrderProductListener implements ApplicationListener<OrderProductEvent> {/** 使用 onApplicationEvent 方法对消息进行接收处理 */@SneakyThrows@Overridepublic void onApplicationEvent(OrderProductEvent event) {String orderId = event.getOrderId();long start = System.currentTimeMillis();Thread.sleep(2000);long end = System.currentTimeMillis();log.info("{}:校验订单商品价格耗时:({})毫秒", orderId, (end - start));}}

③ 定义发布者

// 发布事件,通过 ApplicationEventPublisher 发布事件@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {/** 注入ApplicationContext用来发布事件 */private final ApplicationContext applicationContext;/*** 下单** @param orderId 订单ID*/public String buyOrder(String orderId) {long start = System.currentTimeMillis();// 1.查询订单详情// 2.检验订单价格 (同步处理)applicationContext.publishEvent(new OrderProductEvent(this, orderId));// 3.短信通知(异步处理)long end = System.currentTimeMillis();log.info("任务全部完成,总耗时:({})毫秒", end - start);return "购买成功";}}

④ 发布消息后,接口收到消息

// 发布消息后,接口收到消息@SpringBootTest
public class OrderServiceTest {@Autowired private OrderService orderService;@Testpublic void buyOrderTest() {orderService.buyOrder("732171109");}
}

在这里插入图片描述

② 异步代码的用法

有些业务场景不需要在一次请求中同步完成,比如邮件发送、短信发送等。

开启异步

// 新增@EnableAsync注解@EnableAsync
@SpringBootApplication
public class MingYueSpringbootEventApplication {public static void main(String[] args) {SpringApplication.run(MingYueSpringbootEventApplication.class, args);}
}

② 自定义事件

@Data
@AllArgsConstructor
public class MsgEvent {/** 该类型事件携带的信息 */public String orderId;
}

③ 自定义监听器(推荐使用 @EventListener 注解),使用@Async注解

// 使用@EventListener 注解@Slf4j
@Component
public class MsgListener {@Async@SneakyThrows@EventListener(MsgEvent.class)public void sendMsg(MsgEvent event) {String orderId = event.getOrderId();long start = System.currentTimeMillis();log.info("开发发送短信");log.info("开发发送邮件");Thread.sleep(4000);long end = System.currentTimeMillis();log.info("{}:发送短信、邮件耗时:({})毫秒", orderId, (end - start));}
}

④ 定义发布者

public String buyOrder(String orderId) {long start = System.currentTimeMillis();// 1.查询订单详情// 2.检验订单价格 (同步处理)applicationContext.publishEvent(new OrderProductEvent(this, orderId));// 3.短信通知(异步处理)applicationContext.publishEvent(new MsgEvent(orderId));long end = System.currentTimeMillis();log.info("任务全部完成,总耗时:({})毫秒", end - start);return "购买成功";
}

⑤ 发布消息后,观察同步与异步消息

@Test
public void buyOrderTest() {orderService.buyOrder("732171109");
}

在这里插入图片描述

② SpringBoot+Redis BitMap 实现签到与统计功能

① 什么是Redis BitMap ?

在数据处理和分析中,常常需要对大量的数据进行统计和计算。当数据量达到亿级别时,传统的数据结构和算法已经无法胜任这个任务。Bitmap(位图)是一种适合于大规模数据统计的数据结构,能够以较低的空间复杂度存储大规模数据,并且支持高效的位运算操作。本文将介绍 Bitmap 的基本概念、实现方式和在亿级数据计算中的应用。

在这里插入图片描述

② SpringBoot 整合 Redis 实现签到 功能

① 设计思路

我们可以把年和月作为BitMap的key,然后保存到一个BitMap中,每次签到就到对应的位上把数字从0 变为1,只要是1,就代表是这一天签到了,反之咋没有签到。


比如 2024年1月1日的签到:
Key(202401) Value:1

比如 2024年1月2日的签到:
Key(202401) Value:1

比如 2024年1月3日的未签到:
Key(202401) Value:0

所以2024年一月份的签到状态可以表示为:
Key(202401) Value:1,1,0,1,0,1,1,1


为了区分用户,我们可以加一个用户标识。比如 202401:24ewe89 后面的这个24ewe89是用户的token

② 如何连续签到天数?

在这里插入图片描述


③ 如何得到本月到今天为止的所有签到数据?

在这里插入图片描述


④ 如何从后向前遍历每个Bit位?

在这里插入图片描述
br>

⑤ 代码Demo

// controller@GetMapping("/signCount")
public Result signCount() {return userService.signCount();
}
// servicepublic Result signCount() {//1. 获取登录用户Long userId = UserHolder.getUser().getId();//2. 获取日期LocalDateTime now = LocalDateTime.now();//3. 拼接keyString keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;//4. 获取今天是本月的第几天int dayOfMonth = now.getDayOfMonth();//5. 获取本月截至今天为止的所有的签到记录,返回的是一个十进制的数字 BITFIELD sign:5:202301 GET u3 0List<Long> result = stringRedisTemplate.opsForValue().bitField(key,BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));//没有任务签到结果if (result == null || result.isEmpty()) {return Result.ok(0);}Long num = result.get(0);if (num == null || num == 0) {return Result.ok(0);}//6. 循环遍历int count = 0;while (true) {//6.1 让这个数字与1 做与运算,得到数字的最后一个bit位 判断这个数字是否为0if ((num & 1) == 0) {//如果为0,签到结束break;} else {count ++;}num >>>= 1;}return Result.ok(count);
}

③ 基于Redis实现分布式锁(使用Redisson)

在这里插入图片描述

用法


1. pom文件
   <dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.13.6</version></dependency>
  1. 配置 Redisson 客户端
@Configuration
@SuppressWarnings("all")
public class RedissonConfig {@Beanpublic RedissonClient redissonClient() {Config config = new Config();config.useSingleServer().setAddress("redis://192.168.88.130:6379").setPassword("root");return Redisson.create(config);}}
  1. Redisson 的可重入锁
 @Testpublic void tesRedisson() throws InterruptedException {// 获取可重入锁, 指定锁的名称RLock lock = redissonClient.getLock("anLock");// 尝试获取锁// 参数1:获取锁的最大等待时间(期间会多次重试获取锁)// 参数2:锁自动释放时间// 参数3:时间单位boolean isGetLock = lock.tryLock(1, 10, TimeUnit.SECONDS);if (isGetLock) {try {System.out.println("执行业务");} finally {lock.unlock();}}}

⑤ redis 缓存穿透

什么是缓存穿透?
redis已经没有了,还查询mysql

在这里插入图片描述

解决方案:布隆过滤器
布隆过滤器主要是用于检索一个元素是否在一个集合中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/624669.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

存储卷(数据卷)—主要是nfs方式挂载

1、定义 容器内的目录和宿主机的目录进行挂载 容器在系统上的生命周期是短暂的&#xff0c;一旦容器被删除&#xff0c;数据会丢失。k8s基于控制器创建的pod&#xff0c;delete相当于重启&#xff0c;容器的状态会恢复到原始状态。一旦回到原始状态&#xff0c;后天编辑的文件…

写一个判断鼠标进入方向切换图片的效果

直接看代码&#xff1a; <template><div class"mainrouter centerWindi"><div ref"mouse" class"mouse" mouseenter"handleMouse"></div></div> </template> <script setup> import { onMo…

erlang/OTP 平台(学习笔记)(四)

Erlang语言精要 Erlang shell 相较于日常惯用的系统&#xff0c;Erlang系统是一套更富交互性的环境。使用大部分编程语言时&#xff0c;要么把程序编译成OS可执行文件后运行&#xff0c;要么用解释器来执行一堆脚本文件或编译后的字节码文件。无论哪种情况&#xff0c;都是让…

LeetCode:82. 删除排序链表中的重复元素 II(C++、Java)

目录 82. 删除排序链表中的重复元素 II 题目描述&#xff1a; 实现代码与解析&#xff1a; 链表遍历&#xff1a; 实现代码与解析&#xff1a; 82. 删除排序链表中的重复元素 II 题目描述&#xff1a; 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复…

美颜技术对比:如何根据项目选择不同的美颜SDK?

各位开发者应该非常清楚&#xff0c;为了在项目中取得最佳效果&#xff0c;选择合适的美颜SDK至关重要。本篇文章&#xff0c;笔者将通过对比不同美颜SDK的关键特性&#xff0c;帮助开发者根据项目需求做出明智的选择。 一、技术原理对比 不同的美颜SDK可能采用不同的技术原理…

汽车线束的汽配企业MES管理系统解决方案

随着科技的飞速发展和环保需求的日益提升&#xff0c;新能源汽车在全球范围内崭露头角&#xff0c;成为未来出行的主导力量。在这股浪潮中&#xff0c;中国凭借其强大的研发实力和市场敏锐度&#xff0c;迅速崛起为新能源汽车领域的佼佼者。而作为汽车数字化控制与智能化应用的…

Unity中URP下的SimpleLit顶点着色器

文章目录 前言顶点着色器1、GPU Instance 相关2、顶点输入数据相关3、雾效混合因子4、对 uv 进行 Tilling 和 Offset 的应用 及 把顶点的坐标信息传给输出结构体5、把法线相关的结果&#xff0c;传给输出结构体6、光照贴图相关7、额外灯相关计算8、阴影相关 前言 在上一篇文章…

elementui-树形控件实现子节点右侧添加图标和数据,鼠标放上去显示文字

1、代码 <el-treev-loading"nameLoding":data"data"node-key"id":highlight-current"true"empty-text"暂无数据":props"defaultPropsIndex"default-expand-all:filter-node-method"filterNodeIndex"…

LeetCode 226. 翻转二叉树

226. 翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,…

redis 从0到1完整学习 (十八):阻塞/非阻塞 IO

文章目录 1. 引言2. redis 源码下载3. I/O 模型3.1 阻塞 I/O3.2 非阻塞 I/O 4. 参考 1. 引言 前情提要&#xff1a; 《redis 从0到1完整学习 &#xff08;一&#xff09;&#xff1a;安装&初识 redis》 《redis 从0到1完整学习 &#xff08;二&#xff09;&#xff1a;red…

jetlinks 规则编排中的函数节点使用 js 脚本格式化输出当前系统时间的坑

网上搜到的都是类似如下这种&#xff1a; // 获取当前时间 var date new Date();// 格式化输出当前时间 var year date.getFullYear(); var month date.getMonth(); var day date.getDate(); var hour date.getHours(); var minute date.getMinutes(); var second date.…

捷为科技亮相2024深圳PMO年度论坛 探讨项目管理赋能企业数字化转型

1月13日&#xff0c;一场聚焦项目管理创新与数字化转型的盛会——2024年深圳PMO年度论坛在深圳新一代产业园隆重举行。本次论坛以“项目管理赋能企业数字化转型”为主题&#xff0c;汇聚了众多行业专家、学者和企业代表&#xff0c;共同探讨如何通过项目管理推动企业数字化转型…

电商概念之商品模型

1、基本定义 广义定义&#xff1a;商品是为了出售而生产的劳动成果&#xff0c;人类社会生产力发展到一定历史阶段的产物&#xff0c;用于交换的劳动产品。 电商商品基本概念&#xff1a; 商品类目商品属性销售属性商品编码&商品规格编码SKU和SPU… 2、商品类目 电商平…

【动态规划】20子数组系列_环形子数组的最大和_C++(medium)

题目链接&#xff1a;leetcode环形子数组的最大和 目录 题目解析&#xff1a; 算法原理 1.状态表示 2.状态转移方程 3.初始化 4.填表顺序 5.返回值 编写代码 题目解析&#xff1a; 题目让我们求返回 nums 的非空 子数组 的最大可能和 这道题如果是按照-这道题-是不对…

基于信号完整性的一些PCB设计建议

最小化单根信号线质量的一些PCB设计建议 1. 使用受控阻抗线&#xff1b; 2. 理想情况下&#xff0c;所有信号都应该使用完整的电源或地平面作为其返回路径&#xff0c;关键信号则使用地平面作为返回路径&#xff1b; 3. 信号的返回参考面发生变化时&#xff0c;在尽可能接近…

JMeter笔记(三)

个人学习笔记&#xff08;整理不易&#xff0c;有帮助点个赞&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_weixin_42717928的博客-CSDN博客 目录 一&#xff1a;参数化方法 1&#xff09;用户定义的变量 2&#xff09;函数助手 3&#xff09;…

MYSQL的事务隔离

本章概览 mysql是一个支持多引擎的系统&#xff0c;并不是所有引擎都支持事务&#xff0c;本篇以innodb为例解析mysql在事务支持的实现。提到事务一定会想到ACID(Atomicity、Consistency、Isolation、Durability&#xff0c;即原子性、一致性、隔离性、持久性)&#xff0c;今天…

旧路由重置新路由设置新路由设置教程|适用于PPPoE拨号

前言 前几天朋友说路由器想要重置&#xff0c;但不知道怎么弄。所以就想着只帮忙重置路由器的话&#xff0c;只能帮到一个人。但把整个过程写成图文&#xff0c;就可以帮助更多人。 本文章适合电脑小白&#xff0c;请注意每一步哦&#xff01; 注意事项 开始之前需要确认光猫…

pod控制器的作用

pod控制器的作用 1、动态pv和pvc deployment是控制器 pod空气器:工作负载&#xff0c;workload用于管理pod的中间层&#xff0c;确保podi资源符合预期的状态 预期状态 1、副本数 2、容器重启策略 3、镜像拉取策略 pod、出现故障时重启等等 pod的控制器类型 1、replic…

删除运行框中的文件打开历史记录

当我们使用everything、百度、迅雷等软件&#xff0c;在列表中右键选中打开文件夹时。 当使用 winR 快捷键等方式打开运行时&#xff0c;输入盘符会出现之前打开过的文件夹&#xff0c; 一方面展示的特别多会比较混乱&#xff0c;另一方面 记得在之前的window版本中&#xff08…