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

Redis与IO多路复用

1. Redis与IO多路复用概述

1.1 Redis的单线程特性

Redis是一个高性能的键值存储系统,其核心优势之一便是单线程架构。在Redis 6.0之前,其所有网络IO和键值对的读写操作都是由一个主线程顺序串行处理的。这种设计简化了多线程编程中的锁和同步问题,同时避免了上下文切换的开销,提高了性能。

  • 性能优势:单线程模型使得Redis在处理请求时避免了多线程切换的开销,减少了系统资源的消耗,从而在处理高并发请求时表现出色。
  • 简化开发:由于Redis的单线程特性,开发者无需担心数据一致性和线程安全问题,这大大简化了Redis的开发和维护工作。
  • 资源利用:尽管Redis是单线程的,但其对CPU的利用率并不高,因为Redis的操作大多是内存操作,而内存操作的速度远快于CPU处理速度。因此,Redis的性能瓶颈通常在于内存大小和网络IO,而非CPU。

1.2 IO多路复用的定义与作用

IO多路复用是一种处理并发IO请求的技术,它允许单个线程监视多个文件描述符(file descriptors),以确定哪些文件描述符已经准备好进行IO操作。这项技术的核心在于能够在单个线程中高效地处理多个并发连接,而无需为每个连接创建一个线程。

  • 定义:IO多路复用模型允许一个线程处理多个输入/输出通道。当某个通道有数据可读或可写时,该线程会被通知,然后执行相应的操作。
  • 提高效率:通过IO多路复用,Redis能够使用一个线程来管理多个客户端连接,减少了线程创建和销毁的开销,提高了资源利用率和系统吞吐量。
  • 减少延迟:IO多路复用减少了等待IO操作完成的时间,因为它允许线程在多个连接之间快速切换,而不是阻塞等待单个连接的IO操作完成。
  • 技术实现:Redis通过使用如selectpollepoll(在Linux上)这样的系统调用来实现IO多路复用。其中,epoll是Linux特有的,提供了更高的性能和可扩展性,它通过注册文件描述符事件来实现高效的IO多路复用。

综上所述,Redis的单线程特性和IO多路复用技术的结合,使得Redis在处理高并发请求时表现出了卓越的性能和效率。这种设计不仅简化了系统的复杂性,还提高了对资源的利用效率,是Redis高性能的关键因素之一。

2. Redis的IO多路复用实现

2.1 Redis的文件事件处理器

Redis的文件事件处理器是其网络通信的核心组件,它基于Reactor模式实现,负责处理多个套接字上的事件。这个处理器能够同时监听多个套接字,并在套接字准备好执行操作时响应。

  • 文件事件分类:Redis中的文件事件主要分为可读(AE_READABLE)和可写(AE_WRITABLE)两大类。当套接字有数据可读或可写时,会产生相应的文件事件,文件事件处理器会调用与这些事件关联的处理器来处理事件。
  • 事件处理器组成:文件事件处理器由套接字、I/O多路复用程序、文件事件分派器和事件处理器组成。套接字负责与客户端的通信;I/O多路复用程序负责监听多个套接字;文件事件分派器接收I/O多路复用程序传来的事件,并根据事件类型调用相应的事件处理器;事件处理器定义了在特定事件发生时,服务器应该执行的动作。
  • 性能数据:在高负载情况下,Redis的文件事件处理器能够处理每秒数十万次的请求,这得益于其高效的事件处理机制。根据Redis官方性能测试,使用epoll的Redis实例在处理100,000个并发连接时,能够达到每秒处理120,000次请求的性能。

2.2 Linux内核函数select, poll, epoll的应用

在Linux系统中,Redis通过select、poll和epoll这三个系统调用来实现IO多路复用。

  • select函数:select是最早的IO多路复用实现,它允许程序同时监视多个文件描述符,以确定哪些文件描述符已经准备好进行IO操作。select的主要限制是它只能监视1024个文件描述符,并且在检查文件描述符时需要在用户空间和内核空间之间复制数据,这在大量文件描述符的情况下会导致性能问题。
  • poll函数:poll克服了select监视文件描述符数量的限制,但它仍然需要在用户空间和内核空间之间复制数据。poll使用链表来管理文件描述符,这使得它能够处理超过1024个文件描述符,但随着文件描述符数量的增加,性能也会受到影响。
  • epoll函数:epoll是Linux特有的IO多路复用实现,它提供了比select和poll更高的性能和可扩展性。epoll通过在内核中维护一个文件描述符事件表来减少数据复制,并且只通知那些真正发生了事件的文件描述符。这使得epoll在处理大量并发连接时,能够保持高性能和低延迟。
  • 性能对比:根据Redis的基准测试,在使用epoll时,Redis能够处理的并发连接数是使用select的8倍以上。在100,000个并发连接的测试中,epoll的平均延迟比select低60%以上。这些数据表明,epoll在处理大量并发连接时,提供了显著的性能优势。

3. Redis性能与IO多路复用

3.1 基于内存操作的优势

Redis的性能优势在很大程度上归功于其基于内存的操作。所有数据都存储在内存中,这意味着数据的读取和写入操作都是直接在内存中进行,无需磁盘I/O的开销。

  • 速度对比:基于内存的操作速度比磁盘操作快几个数量级。据研究表明,内存的访问速度大约是磁盘的1000倍。因此,Redis能够以极高的速度处理请求,尤其是在读操作占主导的场景中。
  • 操作效率:由于Redis的数据存储在内存中,数据操作的时间复杂度通常为O(1),这意味着无论数据量大小,操作的时间都是恒定的。这种常数时间复杂度的性能保证了Redis在面对大量数据时依然能够保持高性能。
  • 性能数据:在实际的性能测试中,Redis能够达到每秒数十万次的读写操作。例如,在一项基准测试中,Redis在处理简单的SET和GET命令时,可以达到每秒80万次的吞吐量。

3.2 数据结构的简单性

Redis的性能还得益于其简单的数据结构设计。Redis支持的数据结构包括字符串、列表、集合、哈希表和有序集合,这些数据结构都是经过优化的,以支持快速的数据访问和修改操作。

  • 优化的数据结构:Redis的每种数据结构都是为了特定的用例而优化的。例如,列表使用双向链表实现,支持高效的推入和弹出操作;哈希表使用散列表实现,支持快速的查找和更新操作。
  • 内存效率:Redis的数据结构设计考虑了内存效率。例如,整数集合使用位数组存储元素,这比传统的数组或链表更加节省空间。
  • 性能数据:在处理复杂的数据结构操作时,Redis依然能够保持高性能。例如,在处理有序集合的ZRANGE操作时,Redis能够以微秒级别的延迟返回结果,这对于需要快速排序和检索的场景非常重要。

3.3 多路复用和非阻塞I/O的结合

Redis的高性能也得益于其IO多路复用和非阻塞I/O的结合使用。这种模型允许Redis在单线程中高效地处理多个客户端请求,而不会因为I/O操作而阻塞。

  • 非阻塞I/O:Redis的I/O操作是非阻塞的,这意味着当一个I/O操作正在进行时,Redis可以处理其他请求。这种非阻塞的特性使得Redis能够在等待I/O操作完成的同时,继续处理其他客户端的请求。
  • 多路复用:通过使用epoll(在Linux上)等多路复用技术,Redis可以监视多个文件描述符,以确定哪些文件描述符已经准备好进行I/O操作。这种技术使得Redis能够同时处理成千上万的客户端连接,而不会因为单个慢速I/O操作而降低性能。
  • 性能数据:在实际的性能测试中,使用epoll的Redis实例在处理100,000个并发连接时,能够达到每秒处理120,000次请求的性能。这一数据表明,IO多路复用和非阻塞I/O的结合使用显著提高了Redis的性能和可扩展性。

4. Redis的瓶颈与优化

4.1 网络IO的潜在瓶颈

尽管Redis通过IO多路复用技术实现了高效的网络IO处理,但在某些情况下,网络IO仍然可能成为性能瓶颈。

  • 网络带宽限制:Redis的网络IO性能受限于服务器的网络带宽。在高负载情况下,如果带宽不足以支持数据的快速传输,就可能成为瓶颈。根据测试数据,Redis在10GbE网络上能够达到更高的吞吐量,而在1GbE网络上则会受到限制。
  • 数据包大小:Redis处理的数据包越大,网络IO的时间消耗就越多。对于大型数据传输,即使是在高带宽网络上,单个数据包的处理时间也可能成为性能瓶颈。
  • 网络延迟:网络延迟对Redis的性能影响显著。在跨地域部署的Redis集群中,网络延迟可能导致命令执行的延迟增加,影响整体性能。

4.2 连接瓶颈的处理

为了解决连接瓶颈问题,Redis采取了多种策略来优化性能。

  • 优化连接数:Redis通过调整maxclients配置来限制最大客户端连接数,防止过多的连接消耗服务器资源。根据实际服务器的硬件配置和网络条件,合理设置maxclients值,可以避免因连接数过多而导致的性能下降。
  • 使用连接池:客户端使用连接池可以减少连接建立和销毁的开销。通过复用已有的连接,避免了频繁的网络握手和连接建立,从而提高了性能。
  • 负载均衡:在Redis集群中,通过合理的数据分片和负载均衡,可以将请求分散到不同的节点上,避免单个节点因连接过多而成为瓶颈。
  • 异步处理:Redis 6.0引入了多线程来处理客户端的读写请求,这样可以并行处理多个socket的读写操作,减少了主线程的负担,提高了处理效率。
  • 监控和调优:通过监控工具如redis-clislowlog功能,可以识别和优化慢查询命令。同时,根据监控数据调整配置参数,如timeouttcp-keepalive,以优化网络连接性能。

通过上述措施,Redis能够有效地处理连接瓶颈问题,保持高性能的网络IO处理能力。

5. Redis 6.0的多线程变化

5.1 多线程IO读写任务的引入

Redis 6.0版本引入了多线程IO读写任务,这一变化是为了解决长期困扰Redis的性能瓶颈问题——网络IO处理能力。在新版本中,Redis的网络IO操作(包括读取和写入)可以由多个线程并行处理,而命令的执行仍然由主线程顺序串行处理。

  • 多线程IO的引入:Redis 6.0通过引入io-threads配置参数,允许用户指定用于处理IO操作的线程数。这些线程被称为IO线程,它们负责处理客户端的socket读写操作,而命令的解析和执行仍然由主线程负责。这一设计允许Redis在不牺牲单线程模型简单性和一致性的前提下,提高网络IO的性能。

  • IO线程的工作机制:IO线程通过轮询的方式从主线程接收待处理的socket连接,然后并行执行读写操作。主线程在分配完任务后,会阻塞等待IO线程完成读写任务。这种设计使得多个socket的读写操作可以并行执行,从而提高了整体的网络IO处理能力。

  • 配置和限制:Redis 6.0建议在至少有4个核心的机器上启用2或3个IO线程,在8核心机器上建议启用6个IO线程。官方建议线程数不应超过8个,因为超过这个数量后,性能提升的效果并不明显。

5.2 多线程对性能的影响

Redis 6.0引入多线程后,对性能的影响是显著的。多线程IO读写任务的引入,使得Redis能够更有效地利用多核CPU资源,提高了网络IO的性能,尤其是在高并发场景下。

  • 性能提升:根据Redis官方和社区的测试,启用多线程后,Redis在处理GET/SET命令时的性能几乎翻倍。在4线程IO的情况下,性能相比单线程有显著提升。这一结果表明,多线程能够有效提高Redis的吞吐量和响应速度。

  • 资源利用:多线程的引入使得Redis能够更好地利用服务器的CPU资源。在多核CPU环境中,多线程可以并行处理多个IO请求,减少了主线程的负担,提高了CPU的利用率。

  • 可扩展性:多线程的引入提高了Redis的可扩展性。在面对大规模并发请求时,Redis可以通过增加IO线程的数量来提高性能,而不需要对现有的单线程模型进行复杂的修改。

  • 线程安全问题:尽管多线程的引入带来了性能上的提升,但也引入了线程安全问题。Redis 6.0通过将命令执行保持在主线程中,避免了多线程环境下的并发读写问题,确保了数据的一致性和线程安全性。

综上所述,Redis 6.0的多线程变化是对Redis性能和可扩展性的一次重要提升,它使得Redis能够更好地适应现代多核CPU环境和高并发场景的需求。

6. 总结

6.1 Redis与IO多路复用的协同效应

Redis的单线程架构与IO多路复用技术的结合,为高并发场景下的性能优化提供了有效的解决方案。通过这种设计,Redis能够在保持代码简洁和易于维护的同时,实现对大量并发连接的高效处理。IO多路复用技术使得Redis能够在单个线程中管理多个文件描述符,减少了线程切换的开销,并提高了系统的吞吐量。

6.2 性能优势的具体体现

Redis的性能优势主要体现在以下几个方面:

  • 内存操作的速度:由于所有数据都存储在内存中,Redis能够以接近内存速度的速率处理请求,这是其高性能的关键因素之一。
  • 高效的数据结构:Redis的数据结构设计简单且经过优化,支持快速的数据访问和修改操作,进一步增强了性能。
  • IO多路复用与非阻塞I/O:这种模型使得Redis能够在单线程中高效地处理多个客户端请求,不会因为I/O操作而阻塞,提高了资源利用率和响应速度。
  • 多线程IO读写任务:Redis 6.0引入的多线程IO读写任务进一步提升了网络IO的性能,尤其是在高并发场景下,使得Redis能够更有效地利用多核CPU资源。

6.3 面对的挑战与优化策略

尽管Redis通过IO多路复用和多线程技术实现了高性能,但在网络IO和连接数方面仍面临潜在的瓶颈。为了解决这些问题,Redis采取了包括优化连接数、使用连接池、负载均衡和异步处理等策略。这些措施有助于提高Redis的可扩展性和网络IO处理能力。

6.4 未来的发展方向

随着Redis 6.0多线程特性的引入,Redis未来的发展方向将更加注重性能和可扩展性的提升。多线程的引入为Redis打开了新的可能性,使其能够更好地适应现代多核CPU环境和高并发场景的需求。同时,Redis将继续优化其内存管理和数据结构,以保持其在高性能键值存储解决方案中的领先地位。

相关文章:

Redis与IO多路复用

1. Redis与IO多路复用概述 1.1 Redis的单线程特性 Redis是一个高性能的键值存储系统,其核心优势之一便是单线程架构。在Redis 6.0之前,其所有网络IO和键值对的读写操作都是由一个主线程顺序串行处理的。这种设计简化了多线程编程中的锁和同步问题&…...

基于Java和Vue实现的上门做饭系统上门做饭软件厨师上门app

市场前景 生活节奏加快:在当今快节奏的社会中,越来越多的人因工作忙碌、时间紧张而无法亲自下厨,上门做饭服务恰好满足了这部分人群的需求,为他们提供了便捷、高效的餐饮解决方案。个性化需求增加:随着人们生活水平的…...

spi 回环

///tx 极性0 (sclk信号线空闲时为低电平) /// 相位0 (在sclk信号线第一个跳变沿进行采样) timescale 1ns / 1ps//两个从机 8d01 8d02 module top(input clk ,input rst_n,input [7:0] addr ,input …...

数据库审计工具--Yearning 3.1.9普民的使用指南

1 页面登录 登录地址:18000 (不要勾选LDAP) 2 修改用户密码 3 DML/DDL工单申请及审批 工单申请 根据需要选择【DML/DDL/查询】中的一种进行工单申请 填写工单信息提交SQL检测报错修改sql语句重新进行SQL检测,如检测失败可以进行SQL美化后…...

JAVA接口代码示例

public class VehicleExample {// 定义接口public interface Vehicle {void start(); // 启动车辆void stop(); // 停止车辆void status();// 检查车辆状态}public interface InnerVehicleExample {void student();}// 实现接口的类:Carpublic static class Car imp…...

【Android】Proxyman 抓 HTTP 数据包

前言 抓包(Packet Capture)是指在网络通信中截取、分析数据包的过程。 抓包通常用于网络调试、性能优化、安全分析等工作,可以帮助开发者或运维人员查看网络请求的详细内容,包括请求的URL、请求头、响应状态、数据内容等信息。 …...

基于Java Springboot活力健身馆管理系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 数据…...

Excel SUMIFS

SUMIFS 是 Excel 中一个非常强大的函数,用于根据多个条件对数值区域进行求和。它是 SUMIF 函数的升级版,能够处理多个条件,使得数据分析变得更加精确和方便。 SUMIFS 函数的语法 excel 复制代码 SUMIFS(sum_range, criteria_range1, criteri…...

复制Qt项目后常见问题解决

前言 很多时候因为我们不想在原有的重要代码上作修改,常常将代码复制一份。今天讨论的就是代码复制后,复制的代码运行不正常或出错的问题。 第一个问题:图片等资源文件运行时加载失败 当我将程序运行起来后,我发现有些图片没有显…...

C#-WPF 常见类型转换方法(持续更新)

目录 一、普通类型转换 1、Convert类 2、Parse(转String) 3、TryParse(转String) 4、ToString(转String) 5、int转double 6、自定义类型的显示/隐式转换 二、byte[]转ImageSource 方法一 方法二 一、普通类型转换 1、Convert类 提供了一种安全的方式来执行类型转换&…...

Path does not exist: file:/D:/pythonProject/spark/main/datas/input/u.data

出现标题中的错误原因可能是: 1.文件路径书写错误; 2.文件本身不存在。 从图中可以看出,数据源文件是存在的,但是读取不到文件,说明代码中的文件路径写错了,从报错的结果可以看出,python在D:/…...

物联网——UNIX时间戳、BKP备份寄存器、RTC时钟

RTC时钟 Unix时间戳 UTC/GMT 时间戳转换 时间戳转换 BKP简介 RTC框图 RTC基本结构 硬件供电电路 RTC操作注意事项 接线图(读写备份寄存器和实时时钟)...

力扣 LeetCode 94. 二叉树的中序遍历(Day6:二叉树)

解题思路&#xff1a; 方法一&#xff1a;递归&#xff08;左中右&#xff09; class Solution {List<Integer> res new ArrayList<>();public List<Integer> inorderTraversal(TreeNode root) {recur(root);return res;}public void recur(TreeNode root…...

删除缓存之后,浏览器显示登录新设备

小小记录一下问题&#xff0c;清c盘正好就遇到了【答案AI生成】 清除c盘缓存&#xff0c;浏览器所有页面都需要重新登录&#xff0c;并在登录之后显示登录了新设备是为什么&#xff0c;是因为鉴权更新了就算新设备吗&#xff1f; 回答 清除C盘缓存后&#xff0c;浏览器所有页…...

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04目录1. Alopex: A Computational Framework for Enabling On-Device Function Calls with LLMs摘要&#xff1a;研究背景&…...

Stable diffusion详细讲解

&#x1f33a;系列文章推荐&#x1f33a; 扩散模型系列文章正在持续的更新&#xff0c;更新节奏如下&#xff0c;先更新SD模型讲解&#xff0c;再更新相关的微调方法文章&#xff0c;敬请期待&#xff01;&#xff01;&#xff01;&#xff08;本文及其之前的文章均已更新&…...

软件工程期末复习-用例建模

1、为什么需要用例建模 2、用例建模的表示 3、一个例子&#xff0c;ATM用例图 4、什么是用例&#xff1f; 5、用例包含的软件需求 6、参与者的定义 7、交互<->关联 8、用例建模的步骤 9、确定参与者 10、参与者检查项 11、MINILibrary...

【Golang】——Gin 框架中的表单处理与数据绑定

在 Web 应用开发中&#xff0c;表单是用户与服务器交互的重要手段。Gin 框架对表单处理提供了高效便捷的支持&#xff0c;包括数据绑定、验证等功能。在本篇博客中&#xff0c;我们将详细介绍如何使用 Gin 框架处理表单数据&#xff0c;涵盖基础操作与进阶技巧&#xff0c;帮助…...

hive-内部表外部表-详细介绍

1、表类型介绍 内部表&#xff1a; 表面来看&#xff0c;我们建的所有的表&#xff0c;默认都是内部表&#xff0c;内部表又叫做管理表&#xff0c;它的位置也很固定/user/hive/warehouse下面。 外部表&#xff1a; 创建的时候需要加关键字external 修饰&#xff0c;而且&a…...

Windows系统 ElasticSearch,分词器、Kibana安装

目录 1.wins安装ElasticSearch1.下载es安装包2.下载分词器3.注意事项4.学会看报错日志 2.将 elasticsearch 以服务的方式安装安装ES解压到根盘符下&#xff0c;如C或E盘等&#xff0c;因为 E:\Program Files文件夹下的都是默认的只读权限&#xff0c;所以换到没有只读权限&…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅

目录 前言 操作系统与驱动程序 是什么&#xff0c;为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中&#xff0c;我们在使用电子设备时&#xff0c;我们所输入执行的每一条指令最终大多都会作用到硬件上&#xff0c;比如下载一款软件最终会下载到硬盘上&am…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

6.9-QT模拟计算器

源码: 头文件: widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMouseEvent>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr);…...