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

黑马苍穹外卖技术亮点 详情

1.使用工厂模式和策略模式实现布隆过滤器解决缓存穿透问题

Bitmap

Bitmap是一种数据结构,它使用位图来表示数据。在处理大量数据时,Bitmap可以通过将每个数据元素映射到一个位,然后使用位运算来对数据进行操作。
通过使用Bitmap,我们可以快速地完成排序、查找和去重等操作。优点极大的节省储存空间。但是,Bitmap也存在一些局限性,例如它只能表示有限的数值类型,并且对于数据稀疏的情况可能不太适用。

布隆过滤器

布隆过滤器是一种用于快速检索一个元素是否可能存在于一个集合中的数据结构
它的基本原理是利用多个哈希函数,将一个元素映射成多个位,然后将这些位设置为1。当查询一个元素时,如果这些位都被设置为1,则认为元素可能存在于集合中。布隆过滤器的优点在于它的内存占用极少,并且不局限于数值类型。但是,由于哈希冲突的存在,布隆过滤器也存在误判的可能。

缓存穿透

访问的资源不存在,而导致这个不存在的数据每次请求都要到数据库中去查询,导致数据库挂掉

用布隆过滤器解决缓存穿透问题

不直接访问数据库,而是先通过布隆过滤器判断访问的资源是否存在,存在则放行,不存在则拦截。
使用BitMap作为布隆过滤器,通过多个哈希函数来将被访问的元素映射到位数组中的多个位置上,将对应的位置设置为1。
当需要判断一个元素是否在布隆过滤器中时:只需将该元素进行多次哈希,并检查对应的位数组位置是否都为1,如果其中有任意一位为0,则说明该元素不在集合中;如果所有位都为1,则说明该元素可能在集合中(因为有可能存在哈希冲突),需要进一步检查。

使用工厂模式和策略模式解决缓存穿透问题

  1. 定义布隆过滤器接口:首先定义一个布隆过滤器接口,包括添加元素和判断元素是否存在两个基本操作。
  2. 实现具体的布隆过滤器类:创建类,实现布隆过滤器接口中的方法。在这个类中,需要定义布隆过滗器的数据结构(比如位数组)、大小等属性。
  3. 定义哈希策略接口:定义一个哈希策略接口,包含计算哈希值的方法。
  4. 实现具体的哈希策略类创建多个具体的哈希策略类,每个类对应一种哈希函数的计算方法
  5. 创建布隆过滤器工厂类:定义一个布隆过滤器工厂类,其中包含一个用于创建布隆过滤器对象的工厂方法。工厂方法接受布隆过滤器的大小和哈希策略对象作为参数,并返回一个具体的布隆过滤器对象。
  6. 使用布隆过滤器工厂:在需要创建布隆过滤器对象的地方,调用布隆过滤器工厂的工厂方法来创建布隆过滤器对象,并传入相应的哈希策略对象。
    总结:使用策略模式是创建多个具体的哈希策略类,每个类对应一种哈希函数。并且创建布隆过滤器的工厂类。
    当需要创建布隆过滤器对象时,直接调用工厂类并传入相应的哈希策略对象。
    这样可以将对象的创建和哈希函数的选择解耦,更灵活的创建对象和选择哈希函数。

好处

使用工厂模式和策略模式来实现布隆过滤器带来以下好处:

(1)解耦性:工厂模式和策略模式的结合可以将对象的创建和哈希函数的选择分离,使得各部分之间的耦合度降低。这样在需要修改布隆过滤器的具体实现或者切换哈希函数时,只需要修改相应的工厂类或策略类,而不影响其他部分。
(2)可扩展性:通过工厂模式和策略模式,我们可以方便地添加新的布隆过滤器实现类和哈希函数策略类,而不需要修改现有代码。这样在需要增加新的布隆过滤器类型或者新的哈希函数时,只需添加相应的类即可。

2.使用Redis采用一主两从+哨兵的集群方案

使用Redis

当用户数量较多时,用户频繁的访问数据库,数据库压力增大,系统的性能下降。因此使用Redis对数据进行缓存,减小数据库的压力,提高系统的性能和访问速度。

为什么采用一主两从+哨兵的集群方案(解决高并发高可用问题)

进一步提高Redis的并发能力,可以搭建主从集群,实现读写分离
我们项目的redis采用一主二从的集群方案,主节点负责写数据,从节点负责读数据,主节点写入数据之后,需要把数据同步到从节点中,实现了读写分离,解决了高并发问题
哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送ping命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
哨兵可以实现自动故障修复:哨兵可以监测到主节点宕机,自动将从节点切换为主节点并发布通知其他从服务器修改配置文件,当旧主服务器恢复后会成为一个新的从节点。

怎样解决高并发高可用问题

主从集群保证高并发,哨兵保证高可用。

怎样解决数据一致性问题

数据一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致。
​使用旁路缓存模式在缓存与数据库双写时保持一致性。
先更新数据库,后删除缓存。理论上会出现不一致的情况,但概率较小因为缓存的写入速度是比数据库的写入速度快很多。

**更新缓存替换为删除缓存**,那么**下一次执行的查询操作都会从数据库中加载数据**,此时数据一致性就有了保证。
比较方法时注意:缓存被清空后,线程只能到数据库中查询,在数据库中查完就会直接更新缓存。
先查缓存,再查数据库。
**重点在与看结束后数据库与缓存是否一致,用多久一致的。**
1)先删缓存,再更新数据库:
(多线程调度不确定)可能会导致A删缓存,B去查缓存“空”-->然后去查数据库-->拿着数据库中数据更新缓存-->A更新数据库
结束后:数据库中是A更新后的信息,缓存中是原始信息。(2)先更数据库,再删缓存:
A更数据库,B查缓存-->B拿到原始数据-->A删除缓存
结束后:数据库中新数据,缓存被删即还会获得新数据。【从B在数据库拿到原始数据到写到缓存中,但持续时间相比其他方法短】(3)延迟双删:
A删缓存,B去查缓存“空”-->然后去查数据库-->拿着数据库中数据更新缓存-->A更新数据库-->延迟删除缓存
结束后:相比1最后缓存与数据库时一致的,但性能上不如2

总结:采取旁路缓存使缓存和数据库保持数据的一致性,
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
更新的时候,先更新数据库,再删除缓存中对应着数据库更新的数据。

3.使用Spring Task实现订单超时取消,使用WebSocket实现用户催单。

WebSocket

基于TCP的一种新的网络协议。实现了浏览器与服务器全双工通信——浏览器和服务器只需完成一次握手,两者就可以建立连接,双向数据传输。
WebSocket:两边都可以主动通信。
应用场景:网页聊天、视频弹幕,股票信息实时更新(服务器主动推送到网页上的)

订单超时取消流程

客户下单后未支付,订单一直处于“待支付”状态。
使用Spring Task工具的cron表达式设置定时任务触发时间,每分钟检查一次是否存在支付超时的订单,如果存在超时则将订单状态修改为“已取消”。

用户催单流程

用户在小程序中点击催单按钮后,根据用户id查询是否有支付成功的订单,有则调用WebSocke实现服务端向客户端推送消息,展示用户订单和支付成功信息。

4.使用自定义拦截器和JWT令牌实现用户登录认证,用ThreadLocal存储用户ID

用户登录认证流程

(1)用户登录时,发送用户名和密码给服务器,服务器验证通过则生成一个包含用户信息的JWT令牌,并将其发送给客户端。
(2)客户端受到JWT令牌后,保存在本地中,
(3)每当用户发起请求时,将JWT令牌添加到请求头中
(4)服务器端的自定义拦截器会拦截所有请求,从请求头中提取JWT令牌。
(5)拦截器解析JWT令牌,获取用户信息,并将其存储在ThreadLocal中,以避免在每次请求时都去解析JWT令牌。
(6)拦截器可以检查用户是否已经通过认证,通过则处理请求,未通过则返回错误信息。
(7)请求完成后,拦截器remove清楚ThreadLocal里的用户信息

为什么用JWT不用Session

传统的Session用户认证方案:

(1)用户向服务器发送用户名和密码。
(2)服务器验证通过后,在当前**对话(session)**里面保存相关数据,比如用户角色、登录时间等等。
(3)服务器向用户返回一个 session_id,写入用户的 Cookie。
(4)用户随后的每一次请求,都会通过 Cookie将 session_id 传回服务器。
(5)服务器收到 session_id,找到对应的session并获取前期保存的数据,由此得知用户的身份。

这种传统的通过session的方式适用于前后端不分离的情况,因为session是保存在服务器端,因此对于跨域或服务器集群的情况很不友好。
而JWT解决了跨域问题,而且(1)jwt基于json,数据处理方便。(2)使用非对称加密和签名技术,安全性高。(3)资源服务使用JWT,可不依赖认证服务即可完成授权。

为什么用ThreadLocal

ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
这样可以保证线程之间的数据隔离,避免了线程安全问题。

ThreadLocal使用流程

每次执行请求时拦截器将用户信息用set保存在ThreadLocal中,ThreadLocal每次调用set时是一个独立的线程,当另一个用户调用ThreadLocal的set时方法 时,就会新建另一个线程,线程之间互不影响,当对应线程在调用get时候,就会请求到set时候的信息。在拦截器执行过后的方法中添加ThreadLocal线程remove()方法,这样每次请求结束后会将ThreadLocal线程中的数据删除,这样可以防止线程过多内存泄露。

为什么用拦截器不用过滤器、切面

粒度更细: 拦截器可以针对特定的控制器或控制器方法进行拦截,实现精确的拦截逻辑
而过滤器是基于URL路径进行拦截,无法做到针对具体的控制器或方法,切面也是基于切点进行拦截,粒度相对较粗。

5.使用AOP统一记录登录者操作日志

使用AOP切片,将登陆者增删改用户信息的操作信息记录到数据库中。

流程

(1)建表日志信息表
(2)自定义注解,在增删改等方法运行时调用切面
(3)定义切面类,操作者记录:先通过当前请求的请求头拿到JWT令牌并解析出操作者的用户ID,然后记录操作命令和操作时间等信息插入到日志信息表中。

6.使用Redis分布式锁实现高并发商品秒杀,解决超卖问题

为什么不用单体锁

单体应用难以满足实际高并发访问需求,会将单体应用部署到多个tomcat实例上,由负载均衡将请求分发到不同实例上。
单体锁(synchronized、ReentrantLock)是JVM层面的锁,只能控制单个实例上的并发访问安全,多实例下依然存在数据一致性问题。

分布式锁

分布式锁指的是,所有服务中的所有线程都去获取同一把锁,但只有一个线程可以成功的获得锁,其他没有获得锁的线程必须全部等待,直到持有锁的线程释放锁。

RedLock解决Redis集群主从不同步数据丢失问题

Redisson使用主从集群模式,主节点挂掉,从节点没有同步到锁的情况:
使用RedLock,针对Redis中所有节点来进行同步,能够保证超过半数的Redis加锁了才算加锁成功,从而保证并发安全。

解决流程

多用户并发操作的情况下,多个用户尝试购买同一件商品,导致商品库存不足或者超卖。
采用Redis提供的Redisson组件实现Redis分布式锁,来控制并发访问
当一个线程去获取锁,锁的VALUE中存入UUID来保证锁和当前线程绑定
当前线程获取锁成功开始处理业务时,内部会有watch dog看门狗,每隔10s看当前线程是否还持有锁,如果持有则给锁延长生存时间。

当Redis集群部署时,为了解决主节点挂掉从节点没有同步到锁的情况,使用RedLock,针对Redis中所有节点来进行同步,能够保证超过半数的Redis加锁了才算加锁成功,从而保证并发安全。

另外:用户限流,防止同一用户多次秒杀

使用布隆过滤器记录用户和商品ID来解决。
当用户参与秒杀时,判断是否ID是否记录存在布隆过滤器中,不存在证明该用户是第一次参与秒杀改商品,放行继续后续业务;
过滤器中存在,则禁止继续秒杀。

7.基于Redis使用防重Token和lua脚本,防止重复提交订单

lua脚本作用

使用lua脚本实现原子性的查询并删除操作。为了确保即使多个请求同时到达,也只有一个请求能够成功删除Token。

流程

用户发起请求时,服务端生成唯一的token作为信息凭证
将Token存入Redis并设定过期时间,防止Redis内存溢出。
在后续请求中要携带这个Token,服务器收到后,在Redis中通过lua脚本进行原子性的查询并删除操作
如果Token存在并被成功删除说明是第一次请求则继续处理业务生成订单;如果不存在说明是重复请求,则返回错误提示。

相关文章:

黑马苍穹外卖技术亮点 详情

1.使用工厂模式和策略模式实现布隆过滤器解决缓存穿透问题 Bitmap Bitmap是一种数据结构,它使用位图来表示数据。在处理大量数据时,Bitmap可以通过将每个数据元素映射到一个位,然后使用位运算来对数据进行操作。 通过使用Bitmap&#xff0c…...

Python酷库之旅-第三方库Pandas(005)

目录 一、用法精讲 7、pandas.read_clipboard函数 7-1、语法 7-2、参数 7-3、功能 7-4、返回值 7-5、说明 7-6、用法 7-6-1、代码示例 7-6-2、结果输出 8、pandas.DataFrame.to_clipboard函数 8-1、语法 8-2、参数 8-3、功能 8-4、返回值 8-5、说明 8-6、用法…...

javascripr如何设计弹出输入框并在网页内输出输入内容

javascript如何设计弹出输入对话框 这里就需要用到prompt语言 它的语法格式是 prompt(对话框内容) 如何把在对话框里输入内容输出到网页里,需要先定义一个变量,用var或let都可以。 假定变量名为a,代码是 let aprompt(请输入…...

gitee代码初次上传步骤

ps. 前提是已经下载安装gitee 一、在本地项目目录下空白处右击,选择“Git Bash Here” 二、初始化 git init 三、添加、提交代码(注意add与点之间的空格) git add . git commit -m 添加注释 四、连接、推送到gitee仓库 git remote add …...

android调用openssl库

android 调用openssl库 一、openssl安装编译 下载openssl-1.1.1w.tar.gz和android-ndk-r21e-linux-x86_64.zip解压android-ndk-r21e-linux-x86_64.zip到/opt/pj_ssl目录下,然后配置环境 vim ~/.bashrc增加如下内容 export NDK_HOME/opt/pj_ssl/android-ndk-r21e…...

Hugging face Transformers(3)—— Tokenizer

Hugging Face 是一家在 NLP 和 AI 领域具有重要影响力的科技公司,他们的开源工具和社区建设为NLP研究和开发提供了强大的支持。它们拥有当前最活跃、最受关注、影响力最大的 NLP 社区,最新最强的 NLP 模型大多在这里发布和开源。该社区也提供了丰富的教程…...

kubernetes集群部署:环境准备及master节点部署(二)

主机名IPv4地址IPv6地址角色安装组件操作系统k8s130-node190192.168.XX.190240a:XX::190masterkubeadm、kubelet、containerdAnolis OS 8.94.19.91-28.1.an8.x86_64k8s130-node191192.168.XX.191240a:XX::191nodekubeadm、kubelet、cri-oAnolis OS 8.94.19.91-28.1.an8.x86_64k…...

第8篇 智能合约的商业应用场景解析

一、引言 在区块链技术的众多应用中,智能合约无疑是其中的一颗璀璨明珠。它通过自动化、去中心化和不可篡改的特性,为商业世界带来了革命性的变革。今天,我们将一同探索智能合约在十个不同行业中的实际应用,感受其独特的魅力。 二、智能合约的商业应用案例 供应链管理:…...

Zabbix 配置grafana对接

zabbix对接grafana简介 Zabbix与Grafana对接可以实现更加丰富和美观的数据可视化,可以利用Grafana强大的可视化功能来展示Zabbix收集的数据。 Grafana 本身是提供了Zabbix的对接插件,开箱即用,安装好了之后点击 enable 一下就能启用。然后就…...

三相感应电机的建模仿真(2)基于ABC相坐标系S-Fun的仿真模型

1. 概述 2. 三相感应电动机状态方程式 3. 基于S-Function的仿真模型建立 4. 瞬态分析实例 5. 总结 6. 参考文献 1. 概述 前面建立的三相感应电机在ABC相坐标系下的数学模型是一组周期性变系数微分方程(其电感矩阵是转子位置角的函数,转子位置角随时…...

开源全新H5充值系统源码/自定义首页+充值页面/灵活对接上游渠道接口

开源全新H5充值系统源码,系统基于thinkphp框架开发,功能已全完善,可灵活对接其他上游渠道接口,默认对接了大猿人接口,另外可无限制自定义创建充值页面,首页支持后台自定义修改,支持三级分销&…...

Linux查看文件的行数,字数,字节数

介绍 在Linux系统中这统计非常方便,只需要简单的几个命令就可以搞定,这个命令就是 wc。 wc --help 用法:wc [选项]... [文件]...或:wc [选项]... --files0-fromF 输出每个指定文件的行数、单词计数和字节数,如果指定…...

【IO】文件操作

🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. 文件1.1 认识文件1.2 分清操作的是内存还是硬盘1.3 路径1.3.1 目录结构1.3.2 相对和绝对路径 1.4 文本文件…...

代码随想录算法训练营第74天:路径总结[1]

代码随想录算法训练营第74天:路径总结 ‍ A * 算法精讲 (A star算法) 卡码网:126. 骑士的攻击(opens new window) 题目描述 在象棋中,马和象的移动规则分别是“马走日”和“象走田”。现给定骑士的起始坐标和目标…...

用 Emacs 写代码有哪些值得推荐的插件

以下是一些用于 Emacs 写代码的值得推荐的插件: Ido-mode:交互式操作模式,它用列出当前目录所有文件的列表来取代常规的打开文件提示符,能让操作更可视化,快速遍历文件。Smex:可替代普通的 M-x 提示符&…...

自定义注解-手机号验证注解

注解 package com.XX.assess.annotation;import com.XX.assess.util.MobileValidator;import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.*;/*** 手机号校验注解* author super*/ Retention(RetentionPolicy.RUNTIME) Targe…...

华为od-C卷200分题目5 -项目排期

华为od-C卷200分题目5 -项目排期 题目描述 项目组共有N个开发人员,项目经理接到了M个独立的需求,每个需求的工作量不同,且每个需求只能由一个开发人员独立完成,不能多人合作。 假定各个需求之间无任何先后依赖关系,请…...

如何使用Pip从Git仓库安装Python包:深入探索远程依赖管理

如何使用Pip从Git仓库安装Python包:深入探索远程依赖管理 Python的包管理工具Pip使得安装和管理Python库变得非常简单。有时,我们需要安装那些尚未发布到PyPI的包,或者想要尝试最新的开发版本。这时,可以直接从Git仓库安装包。本…...

计算机专业怎么选择电脑

现在高考录取结果基本已经全部出来了,很多同学都如愿以偿的进入到了计算机类专业,现在大部分同学都在为自己的大学生活做准备了,其中第一件事就是买电脑,那计算机类专业该怎么选择电脑呢? 计算机专业是个一类学科&…...

当前国内可用的docker加速器搜集 —— 筑梦之路

可用镜像加速器 以下地址搜集自网络,仅供参考,请自行验证。 1、https://docker.m.daocloud.io2、https://dockerpull.com3、https://atomhub.openatom.cn4、https://docker.1panel.live5、https://dockerhub.jobcher.com6、https://hub.rat.dev7、http…...

云计算——弹性云计算器(ECS)

弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂&#xff…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

爬虫基础学习day2

# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...