MATLAB代码示例,用于实现PID控制器来控制一个简化的机械系统。在这个例子中,我们将使用离散时间PID控制器,并模拟一个质量-弹簧-阻尼系统。
function pid_control_mechanical_system() % PID控制器参数 Kp = 1.0; % 比例系数 Ki = 0.1; % 积分系数 Kd = 0.01; % 微分系数 % 离散PID变量 prev_error = 0; integral = 0; % 模拟参数 dt = 0.01; % 时间步长 t_final = 10; % 模拟总时间 t = 0:dt:t_final-dt; % 时间向量 % 参考信号(例如阶跃信号) reference = ones(size(t)); % 初始条件 position = zeros(size(t)); % 位置 velocity = zeros(size(t)); % 速度 acceleration = zeros(size(t)); % 加速度 force = zeros(size(t)); % 施加在系统上的力(PID控制器的输出) % 机械系统参数 mass = 1; % 质量 damping_coeff = 0.
💻博主现有专栏:
C51单片机(STC89C516),c语言,c++,离散数学,算法设计与分析,数据结构,Python,Java基础,MySQL,linux,基于HTML5的网页设计及应用,Rust(官方文档重点总结),jQuery,前端vue.js,Javaweb开发,Python机器学习等
🥏主页链接:
Y小夜-CSDN博客
目录
🎯不安全的超能力
🎯解引用裸指针
🎯调用不安全函数或方法
🎃创建不安全代码的安全抽象
🎃使用extern函数调用外部代码
🎯访问或修改可变静态变量
🎯实现不安全trait
🎯访问联合体中的字段
目前为止讨论过的代码都有 Rust 在编译时会强制执行的内存安全保证。然而,Rust 还隐藏有第二种语言,它不会强制执行这类内存安全保证:这被称为 不安全 Rust(unsafe Rust)。它与常规 Rust 代码无异,但是会提供额外的超能力。
尽管代码可能没问题,但如果 Rust 编译器没有足够的信息可以确定,它将拒绝代码。
不安全 Rust 之所以存在,是因为静态分析本质上是保守的。当编译器尝试确定一段代码是否支持某个保证时,拒绝一些合法的程序比接受无效的程序要好一些。这必然意味着有时代码 可能 是合法的,但如果 Rust 编译器没有足够的信息来确定,它将拒绝该代码。在这种情况下,可以使用不安全代码告诉编译器,“相信我,我知道我在干什么。” 不过千万注意,使用不安全 Rust 风险自担:如果不安全代码出错了,比如解引用空指针,可能会导致不安全的内存使用。
另一个 Rust 存在不安全一面的原因是:底层计算机硬件固有的不安全性。如果 Rust 不允许进行不安全操作,那么有些任务则根本完成不了。Rust 需要能够进行像直接与操作系统交互,甚至于编写你自己的操作系统这样的底层系统编程!这也是 Rust 语言的目标之一。让我们看看不安全 Rust 能做什么,和怎么做。
🎯不安全的超能力 可以通过 unsafe 关键字来切换到不安全 Rust,接着可以开启一个新的存放不安全代码的块。这里有五类可以在不安全 Rust 中进行而不能用于安全 Rust 的操作,它们称之为 “不安全的超能力。(unsafe superpowers)” 这些超能力是:
解引用裸指针调用不安全的函数或方法访问或修改可变静态变量实现不安全 trait访问 union 的字段 有一点很重要,unsafe 并不会关闭借用检查器或禁用任何其他 Rust 安全检查:如果在不安全代码中使用引用,它仍会被检查。unsafe 关键字只是提供了那五个不会被编译器检查内存安全的功能。你仍然能在不安全块中获得某种程度的安全。
再者,unsafe 不意味着块中的代码就一定是危险的或者必然导致内存安全问题:其意图在于作为程序员你将会确保 unsafe 块中的代码以有效的方式访问内存。
文章目录 C++发展历史1.命名空间1.1 namespace的价值1.2 namespace的定义1.3 命名空间使⽤ 2.C++输⼊&输出3.缺省参数3.1 缺省参数的概念3.2 缺省参数的分类 4.函数重载5.引⽤5.1引⽤的概念和定义5.2 引⽤的特性5.3 const引⽤5.4 使用场景5.5 指针和引⽤的关系 6.内联函数6.1内联函数概念6.2 内敛函数的特性 7.指针空值nullptr7.1 C++98中的指针空值7.2 C++11中的指针空值 8 **总结** C++发展历史 C++的起源可以追溯到1979年,当时Bjarne Stroustrup(本贾尼·斯特劳斯特卢普,这个翻译的名字不同的地⽅可能有差异)在⻉尔实验室从事计算机科学和软件⼯程的研究⼯作。⾯对项⽬中复杂的软件开发任务,特别是模拟和操作系统的开发⼯作,他感受到了现有语⾔(如C语⾔)在表达能⼒、可维护性和可扩展性⽅⾯的不⾜。
1983年,Bjarne Stroustrup在C语⾔的基础上添加了⾯向对象编程的特性,设计出了C++语⾔的雏形,此时的C++已经有了类、封装、继承等核⼼概念,为后来的⾯向对象编程奠定了基础。这⼀年该语⾔被正式命名为C++。
语言的发展是一个初步递进、由浅入深的过程。
目前,C++还在不断向后发展中。
1.命名空间 1.1 namespace的价值 在C/C++中,变量、函数和后⾯要学到的类都是⼤量存在的,这些变量、函数和类的名称将都存在于全局作⽤域中,可能会导致很多冲突。使⽤命名空间的⽬的是对标识符的名称进⾏本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。
c语⾔项⽬类似下⾯程序这样的命名冲突是普遍存在的问题,C++引⼊namespace就是为了更好的解决这样的问题。
#include <stdio.h> #include <stdlib.h> int rand = 10; int main() { // 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数” printf("%d\n", rand); return 0; } 1.2 namespace的定义 • 定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
// 普通的命名空间 namespace N1 // N1为命名空间的名称 { // 命名空间中的内容,既可以定义变量,也可以定义函数 int a; int Add(int x, int y) { return x + y; } } • namespace只能定义在全局,当然他还可以嵌套定义。
目录
一、用法精讲
55、pandas.lreshape函数
55-1、语法
55-2、参数
55-3、功能
55-4、返回值
55-5、说明
55-6、用法
55-6-1、数据准备
55-6-2、代码示例
55-6-3、结果输出
56、pandas.wide_to_long函数
56-1、语法
56-2、参数
56-3、功能
56-4、返回值
56-5、说明
56-6、用法
56-6-1、数据准备
56-6-2、代码示例
56-6-3、结果输出 57、pandas.isna函数
57-1、语法
57-2、参数
57-3、功能
57-4、返回值
57-5、说明
57-6、用法
57-6-1、数据准备
57-6-2、代码示例
57-6-3、结果输出
二、推荐阅读
1、Python筑基之旅
2、Python函数之旅
3、Python算法之旅
4、Python魔法之旅
5、博客个人主页
一、用法精讲 55、pandas.lreshape函数 55-1、语法 # 55、pandas.lreshape函数 pandas.lreshape(data, groups, dropna=True) Reshape wide-format data to long. Generalized inverse of DataFrame.pivot. Accepts a dictionary, groups, in which each key is a new column name and each value is a list of old column names that will be “melted” under the new column name as part of the reshape.
一、异常分类 这里的异常分类从系统处理异常的角度看,主要分类两类:业务异常和系统异常。
1、业务异常 业务异常主要是一些可预见性异常,处理业务异常,用来提示用户的操作,提高系统的可操作性。常见的业务异常提示:
请输入xxxxxx不能为空xxx重复,请更换 2、系统异常 系统异常主要是一些不可预见性异常,处理系统异常,可以让展示出一个友好的用户界面,不易给用户造成反感。如果是一个金融类系统,在用户界面出现一个系统异常的崩溃界面,很有可能直接导致用户流失。
常见的系统异常提示:
页面丢失404服务器异常500 二、应用启动后404界面 1、引入页面Jar包 <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-thymeleaf</artifactid> </dependency> 2、自定义首页接口 import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class IndexController { @RequestMapping("/") public String index(ModelMap modelMap) { modelMap.addAttribute("name","jksadf") ; return "index"; } } 3、首页界面 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8" /> <title></title> </head> <body> <h1 th:text="${name}"></h1> </body> </html> 三、异常处理 1、项目结构图 2、自定义业务异常类 public class ServiceException extends Exception { public ServiceException (String msg){ super(msg); } } 3、自定义异常描述对象 public class ReturnException { // 响应码 private Integer code; // 异常描述 private String msg; // 请求的Url private String url; // 省略 get set 方法 } 4、统一异常处理格式 两个基础注解
目录
一、用法精讲
52、pandas.from_dummies函数
52-1、语法
52-2、参数
52-3、功能
52-4、返回值
52-5、说明
52-6、用法
52-6-1、数据准备
52-6-2、代码示例
52-6-3、结果输出
53、pandas.factorize函数
53-1、语法
53-2、参数
53-3、功能
53-4、返回值
53-5、说明
53-6、用法
53-6-1、数据准备
53-6-2、代码示例
53-6-3、结果输出 54、pandas.unique函数
54-1、语法
54-2、参数
54-3、功能
54-4、返回值
54-5、说明
54-6、用法
54-6-1、数据准备
54-6-2、代码示例
54-6-3、结果输出
二、推荐阅读
1、Python筑基之旅
2、Python函数之旅
3、Python算法之旅
4、Python魔法之旅
5、博客个人主页
一、用法精讲 52、pandas.from_dummies函数 52-1、语法 # 52、pandas.from_dummies函数 pandas.from_dummies(data, sep=None, default_category=None) Create a categorical DataFrame from a DataFrame of dummy variables. Inverts the operation performed by get_dummies(). New in version 1.5.0. Parameters: data DataFrame Data which contains dummy-coded variables in form of integer columns of 1’s and 0’s.
Java IO 流:字节流、字符流、接口、实现类与阻塞方法 1、字节流与字符流1.1 字节流1.2 字符流 2、常见的接口与实现类3、阻塞方法4、总结 💖The Begin💖点点关注,收藏不迷路💖 在 Java 中,IO(Input/Output)流是处理数据输入输出的重要部分。无论是从文件、网络还是其他数据源读取数据,或是将数据写入到这些位置,Java 都提供了丰富的流类库来支持这些操作。下面我们将详细介绍 Java IO 流中的字节流、字符流、常见的接口、实现类以及阻塞方法。
1、字节流与字符流 1.1 字节流 字节流用于处理原始数据,如图片、视频等二进制文件。抽象类: InputStream:代表从数据源(如文件、网络连接等)读取字节的输入流。OutputStream:代表将数据写入目标(如文件、网络连接等)的字节输出流。 常见实现类: FileInputStreamFileOutputStreamBufferedInputStreamBufferedOutputStream 1.2 字符流 字符流用于处理文本数据,如文本文件、网络传输的文本信息等。抽象类: Reader:代表从数据源读取字符的输入流。Writer:代表将数据写入目标的字符输出流。 常见实现类: FileReaderFileWriterBufferedReaderBufferedWriter 2、常见的接口与实现类 Java IO 流库中定义了许多接口和类,包括前面提到的抽象类(如 InputStream、OutputStream、Reader、Writer),以及为了实现这些抽象类而提供的具体实现类。
除了实现类外,还有一些重要的接口:
Closeable:定义了 close() 方法,用于释放与流相关联的系统资源。Flushable:定义了 flush() 方法,用于确保所有待写入的数据都被实际写入目标。Appendable:定义了 append() 方法,主要在字符流中使用。 3、阻塞方法 阻塞方法是指在调用时,如果数据不可用或者未达到特定条件(如文件末尾),则会一直等待的方法。
示例方法: InputStream 和 Reader 中的 read() 方法:当没有数据可读时,会阻塞直到有数据可读或流被关闭。BufferedReader 中的 readLine() 方法:当没有新的一行可读时,会阻塞直到新的一行数据可读或流被关闭。 使用阻塞方法时需要谨慎,因为它们可能导致程序在等待数据时暂停执行,从而影响性能和响应性。在处理大量数据或需要高效处理数据的场景中,可以考虑使用非阻塞方法或异步IO来避免阻塞。
4、总结 Java IO 流库提供了丰富的类和方法来处理数据的输入输出操作。通过字节流和字符流,我们可以方便地处理二进制文件和文本文件。同时,Java IO 流库中的接口和类也为我们提供了灵活的扩展性。
💖The End💖点点关注,收藏不迷路💖
✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,PyQt5,Tkinter,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生k8s,linux,shell脚本等实操经验,网站搭建,数据库等分享。
所属的专栏:Python常见报错以及解决办法集锦
景天的主页:景天科技苑
文章目录 Pandas中`ValueError: cannot reindex from a duplicate axis`错误分析报错原因1. 索引重复2. 不当的索引操作 解决办法1. 去除重复索引2. 使用`reset_index()`3. 自定义处理重复索引 如何避免1. 维护索引的唯一性2. 使用检查3. 谨慎处理合并和连接4. 使用文档和社区资源 总结 Pandas中ValueError: cannot reindex from a duplicate axis错误分析 在Pandas中,ValueError: cannot reindex from a duplicate axis错误通常发生在尝试对包含重复索引的DataFrame或Series进行重新索引(reindex)时。这种错误表明你试图将一个具有重复索引的DataFrame或Series的索引映射到一个新的索引上,但新索引中不允许存在重复项,从而导致了冲突。
报错原因 1. 索引重复 当你尝试重新索引的DataFrame或Series的索引中存在重复项时,而目标索引(即你希望映射到的新索引)是唯一的,这会导致Pandas无法确定如何将重复项映射到目标索引中的相应位置。
2. 不当的索引操作 在某些情况下,错误的索引操作(如合并、连接等)可能导致索引重复,随后在尝试重新索引时触发此错误。
解决办法 1. 去除重复索引 在重新索引之前,首先检查并去除DataFrame或Series中的重复索引。这可以通过drop_duplicates()方法实现,但请注意,这将删除重复的行(或元素),只保留第一个出现的实例。
import pandas as pd # 假设df是一个包含重复索引的DataFrame df = pd.DataFrame({'A': [1, 2, 3, 4]}, index=[0, 1, 1, 2]) # 去除重复索引(注意这会删除重复的行) df_no_duplicates = df[~df.
系列文章目录 一、Spark应用程序启动与资源申请
二、DAG(有向无环图)的构建与划分
三、Task的生成与调度
四、Task的执行与结果返回
五、监控与容错
六、优化策略
文章目录 系列文章目录前言一、Spark应用程序启动与资源申请1. SparkContext的创建2. 资源申请 二、DAG(有向无环图)的构建与划分1. DAG的构建2. DAG的划分3. DAG的调度执行4. DAG调度的优化 三、Task的生成与调度1. Task的生成2. Task的调度 四、Task的执行与结果返回1. Task的执行2. 结果的返回 五、监控与容错1. 监控2. 容错 六、优化策略1. 内存计算2. 智能Shuffle机制3. 资源管理与调度 前言 Spark调度底层执行原理是一个复杂而精细的过程,它涉及到多个组件的交互和协同工作,以实现大数据处理的高效性和灵活性。本文主要对Spark调度底层执行原理进行详细解析。
Spark调度底层执行原理详解图
一、Spark应用程序启动与资源申请 1. SparkContext的创建 当Spark应用程序启动时,首先会创建SparkContext对象。SparkContext是Spark的入口点,负责初始化与资源管理器(如YARN、Mesos等)的连接,注册应用,并请求分配Executor资源。
2. 资源申请 SparkContext向资源管理器注册并向其申请运行Executor。资源管理器分配Executor资源后,启动Executor进程。这些Executor是Spark在每个Worker节点上启动的进程,负责执行具体的Task。
二、DAG(有向无环图)的构建与划分 Spark的DAG(Directed Acyclic Graph,有向无环图)调度原理是Spark作业调度机制的核心部分,它负责将复杂的作业分解成可并行执行的任务集,并通过任务调度器进行高效执行。以下是Spark DAG调度原理的详细解释:
1. DAG的构建 用户代码中包含Transformations(转换操作)和Actions(行动操作)时,Spark会构建一个DAG来表示RDD(弹性分布式数据集)之间的依赖关系。这些依赖关系决定了数据处理的流程。
RDD的依赖关系:
在Spark中,RDD(弹性分布式数据集)是数据处理的基本单位。RDD之间的依赖关系决定了数据处理的流程和顺序。这些依赖关系是有向的,总是由子RDD指向父RDD。DAG的生成:
当用户提交一个Spark作业时,Spark会根据RDD之间的依赖关系构建一个DAG。这个DAG表示了作业中所有RDD之间的转换和行动操作,以及它们之间的数据流动关系。 2. DAG的划分 DAG Scheduler负责将DAG划分为多个Stage(阶段)。Stage的划分依据是RDD依赖关系中的宽依赖(如shuffle操作)。宽依赖标志着数据重分布的需求,自然成为Stage的边界。每个Stage包含一组可以并行执行的Task。Stage的划分:
如果RDD之间的依赖是窄依赖(即一个父RDD的分区只会被一个子RDD的分区使用),则它们会被划分到同一个Stage中。如果依赖是宽依赖(即一个父RDD的分区会被多个子RDD的分区使用,通常涉及shuffle操作),则会在宽依赖处进行Stage的划分。
Task的生成:
每个Stage会被进一步划分为多个Task(任务)。这些Task是Spark实际执行的最小单元,它们将被分发到集群中的Executor上执行。 3. DAG的调度执行 Task的提交与执行:
DAG Scheduler将划分好的Stage提交给Task Scheduler。Task Scheduler负责将Stage中的Task分发到集群的Executor上执行。Executor多线程地执行Task,每个线程负责一个Task。执行结果的收集:
当Task执行完成后,会将结果返回给Task Scheduler。Task Scheduler将结果汇总后,通知DAG Scheduler。DAG Scheduler根据Task的执行结果和Stage的依赖关系,决定是否提交下一个Stage执行。容错与重试:
Docker 安装 RabbitMQ,自定义数据卷位置启动失败,分析过程 问题描述 运行docker命令,RabbitMQ启动失败,且没有特别错误日志 docker run -d -p 5672:5672 -p 15672:15672 --name rabbitmq -v /xzlawin/mydocker/rabbitmq/volume/5672/plugins:/opt/rabbitmq/plugins -v /xzlawin/mydocker/rabbitmq/volume/5672/log:/var/log/rabbitmq -v /xzlawin/mydocker/rabbitmq/volume/5672/data:/var/lib/rabbitmq -v /xzlawin/mydocker/rabbitmq/volume/5672/config:/etc/rabbitmq -e RABBITMQ_DEFAULT_USER=guest -e RABBITMQ_DEFAULT_PASS=guest 6c3c2a225947 分析原因 容器内的文件未同步到数据卷映射的目录上,文件缺失,导致启动失败 分析步骤一,运行docker命令,使用默认数据卷位置,启动成功 docker run -d -p 5672:5672 -p 15672:15672 --name rabbitmq 6c3c2a225947 查看容器ID docker ps 查看数据卷信息 docker inspect [容器ID] 控制台显示
"Mounts": [ { "Type": "volume", "Name": "rabbitmq_log", "Source": "/var/lib/docker/volumes/rabbitmq_log/_data", "Destination": "/var/log/rabbitmq", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "" }, { "
Python+wxauto=微信自动化? 一、wxauto库简介 1.什么是wxauto库 wxauto是一个基于UIAutomation的开源Python微信自动化库。它旨在帮助用户通过编写Python脚本,轻松实现对微信客户端的自动化操作,从而提升效率并满足个性化需求。这一工具的出现,为经常需要在电脑上处理大量通讯信息的用户提供了一个高效的解决方案。
2.wxauto库的特点 跨平台支持:wxauto支持Windows、macOS和Linux等多种操作系统。
简单易用:wxauto提供了丰富的函数和类,使得编写自动化测试脚本变得简单直观。
灵活扩展:wxauto可以轻松地与其他Python库集成,如unittest、pytest等。
二、安装wxauto库 1.使用pip安装 在开始之前,请确保您的系统中已经安装了Python和pip。pip是Python的包管理工具,大多数Python安装程序都会自动包含它。
打开命令行工具(在Windows上是Command Prompt或PowerShell,在macOS和Linux上是Terminal),输入以下命令来安装wxauto库:
pip install wxauto 如果您正在使用一个虚拟环境,请确保该环境已被激活,然后再执行上述命令。
安装过程可能需要几分钟时间,期间pip会下载并安装wxauto及其依赖项。
2.验证安装 为了验证wxauto是否安装成功,您可以创建一个简单的Python脚本来尝试导入wxauto库。以下是验证的步骤:
创建一个名为test_wxauto.py的新Python文件,并在其中输入以下代码:
import wxauto print(wxauto.__version__) 运行这个脚本,您应该在控制台看到wxauto的版本号。如果没有出现错误,即表示wxauto已成功安装。
如果遇到问题,请确认您的Python和pip是否正确安装,且它们的路径已添加到系统环境变量中。
三、编写第一个wxauto基础测试脚本 1.创建一个简单的GUI应用程序 我们将使用Python的wxPython库来创建一个简单的GUI应用程序,该程序将仅包含一个标签和一个按钮。这将是我们使用wxauto进行自动化测试的目标。
首先,确保您已安装wxPython库。可以使用以下命令通过pip安装:
pip install wxPython 接下来,创建一个简单的wxPython应用程序,如下所示:
import wx class MyFrame(wx.Frame): def __init__(self): super().__init__(None, title="Simple GUI") panel = wx.Panel(self) self.label = wx.StaticText(panel, label="Hello, wxauto!", pos=(10, 10)) self.button = wx.Button(panel, label="Click me", pos=(10, 50)) self.button.Bind(wx.EVT_BUTTON, self.on_button_click) self.Show() def on_button_click(self, event): self.label.SetLabel("Hello, wxauto! You clicked the button.
Redis 的多路IO复用 多路I/O复用是一种同时监听多个文件描述符(如Socket)的状态变化,并能在某个文件描述符就绪时执行相应操作的技术。在Redis中,多路I/O复用技术主要用于处理客户端的连接请求和读写操作,以实现高并发、高性能的服务。Redis支持多种多路I/O复用机制,包括select、poll、epoll和kqueue等。其中,epoll是Linux系统下性能最好的一种机制,Redis在Linux系统下默认使用epoll。
select机制 select是最早的多路I/O复用机制,通过调用select函数来监视多个文件描述符的状态变化。但是,select机制存在性能瓶颈和文件描述符数量限制的问题。在高并发场景下,select机制的性能会受到较大影响。
poll机制 poll机制是对select机制的改进,解决了文件描述符数量限制的问题。但是,poll机制在大量文件描述符的情况下仍然存在性能瓶颈。
epoll机制 epoll是Linux特有的I/O多路复用机制,采用事件驱动的方式,通过epoll_ctl函数注册文件描述符的事件,然后通过epoll_wait函数等待I/O事件的发生。epoll机制在处理大量连接时具有更好的扩展性和性能。Redis在Linux系统下默认使用epoll机制。
Redis 单线程抗高QPS的原因 Redis作为一个单线程的内存数据库,却能够抗住如此高的QPS(每秒查询率),这主要得益于以下几个方面:
非阻塞I/O与多路I/O复用 Redis采用了非阻塞I/O与多路I/O复用技术,使得单个线程可以同时处理多个客户端的连接请求和读写操作。当某个文件描述符就绪时,Redis会立即执行相应的操作,而不会阻塞整个线程。这种机制大大提高了Redis的并发处理能力。
纯内存操作 Redis的所有数据都存储在内存中,因此读写操作都非常快。相比于磁盘数据库,Redis的读写性能要高出几个数量级。这也是Redis能够抗住高QPS的重要原因之一。
高效的 数据结构
Redis内部使用了多种高效的数据结构,如哈希表、跳表、整数集合等。这些数据结构在存储和查询数据时都具有较高的性能。同时,Redis还针对这些数据结构进行了大量的优化,以确保在高并发场景下仍然能够保持稳定的性能。
单线程避免了 线程切换和加锁的开销
虽然多线程可以提高系统的并行处理能力,但同时也带来了线程切换和加锁的开销。Redis采用单线程模型,避免了这些开销,使得Redis在处理单个请求时更加高效。此外,单线程模型也使得Redis的编程模型相对简单,易于维护和管理。
Redis在实际应用中抗住高QPS的关键在于其内部设计、数据结构的高效利用以及配置优化。
1. 内部设计 多路I/O复用 机制:Redis通过多路I/O复用技术(如epoll在Linux系统中)实现同时监听多个客户端连接,当某个连接准备就绪时,Redis会立即处理,无需等待或轮询其他连接。假设Redis服务器同时处理1万个客户端连接,当有100个连接同时发送请求时,Redis不会逐一检查每个连接,而是通过epoll机制立即处理这100个连接,从而实现高效并发。 单线程模型 Redis采用单线程模型,避免了多线程间的竞争和锁的开销,使得每个请求都能得到快速处理。在高并发场景下,多线程模型可能因为线程切换和锁的竞争而导致性能下降。而Redis的单线程模型能够确保每个请求都在同一线程中处理,从而避免了这些开销。 2. 数据结构的高效利用 合理选择数据结构 Redis提供了多种数据结构,如字符串、列表、哈希、集合和有序集合。根据业务需求选择合适的数据结构能够大大提高性能。例如,使用哈希表存储用户信息,可以通过用户ID快速定位到用户数据。
缩短键值对存储长度 缩短键值对的存储长度可以减少内存占用和网络传输开销,从而提高性能。例如,可以使用更短的key和value,或者对数据进行压缩后再存储。
3. 配置优化 使用Pipeline 机制:Pipeline允许客户端将多个命令打包成一个请求发送给Redis服务器,从而减少网络往返时间。假设客户端需要执行10个命令,如果使用普通的请求-响应模式,需要发送10次请求和接收10次响应;而使用Pipeline,只需要发送一次请求和接收一次响应,从而大大提高了性能。 启用持久化 机制:Redis提供了RDB和AOF两种持久化方式,以确保数据在服务器重启后不会丢失。根据业务需求选择合适的持久化方式,并调整相关参数以优化性能。例如,可以关闭不必要的持久化功能,或者调整AOF的刷新频率和文件大小等参数。 监控和优化 机制:定期监控Redis的性能指标,如内存使用、QPS、响应时间等,并使用Redis自带的INFO命令或第三方监控工具进行分析和优化。如果发现Redis的内存使用率过高,可以通过增加内存、优化数据结构或调整缓存策略等方式来降低内存占用;如果发现某个命令的响应时间过长,可以通过优化该命令或调整相关参数来提高性能。 Redis Big Key的定位以及解决方案 Redis最常见的用途就是缓存数据来提高系统的性能。但是如果缓存使用不当,如下场景:
业务中使用了不恰当的redis数据结构。如使用String的value存储某个较大二进制文件数据。业务预估不准确;如规划的时候没有对key的成员进行合理的拆分,导致key的成员数据量过多。没有及时清理无用的数据;如List结构中数据持续增加而没有弹出数据的机制,那么数据会越来越多。某个key存放的数据突然的波动很大;如存放某个明星热点粉丝列表或者评论的列表由于明星出轨或者离婚导致热点数据量激增,也就是value存放过多数据。 以上情况都会导致key对应的value数据量比较大,也就是value所占的内存空间较大,这就是所谓的big key问题。针对Redis的big key一般的判定标准如下:
总结起来其实就分成两类,一类是字符型,一类是非字符型(Hash、List、Set、Zset),针对字符型是判断value值大小,针对字符型就是判断其存放的元素个数,如下图的整理:
上面是判定big key的一般标准,具体到每个系统的判断标准还需要根据自身的业务场景来确定。
1、Big Key的常见场景 排行榜: 在排行榜系统中,可能会使用Redis的Sorted Set数据结构来存储用户的分数和排名。如果用户数量非常多,那么这个Sorted Set的大小就会非常大,从而形成大Key。在线课程系统: 在线课程系统可能会使用Redis来存储每个课程的学生列表。如果一个课程的学生数量非常多,那么这个列表就可能会形成大Key。直播系统: 直播系统可能会使用Redis来存储每个直播间的观众列表。如果一个直播间的观众数量非常多,那么这个列表就可能会形成大Key。社交网络: 社交网络可能会使用Redis来存储用户的好友列表或者粉丝列表。如果一个用户的好友或者粉丝数量非常多,那么这个列表就可能会形成大Key。实时计算: 在实时计算场景中,可能会使用Redis来存储中间计算结果。如果这些结果的数据量非常大,那么就可能会形成大Key。 2、Big Key的危害 内存占用过大: Redis是基于内存的数据存储系统,大Key会占用大量的内存空间,可能导致内存不足,影响系统的正常运行。性能下降: 当Redis需要对大Key进行操作时,如读取、写入、删除等,都会消耗大量的CPU和内存资源,导致Redis的性能下降。阻塞问题: Redis是单线程模型,对大Key的操作可能会阻塞其他的请求,导致Redis服务的响应时间增加。数据备份和恢复问题: 如果Redis中存在大Key,那么在进行数据备份和恢复时,可能会因为单个Key的数据过大而导致备份和恢复过程变得非常慢。网络带宽压力: 当Redis需要将大Key的数据传输到客户端时,可能会占用大量的网络带宽,影响网络的性能。内存分配不均匀: 集群架构下,某个数据分片的内存使用率远超其他数据分片,无法使数据分片的内存资源达到均衡。 3、Big Key的检测 Redis大Key的检测可以通过以下几种方式进行:
开发语言:Java框架:springboot+uniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系统展示
商品管理
公告管理
公告类型管理
摘要
超市购物系统利用当下成熟完善的springboot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了收货地址管理、购物车管理、客服聊天管理、字典管理、公告管理、商品管理、商品收藏管理、商品评价管理、商品订单管理、用户管理、管理员管理等功能。超市购物系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
研究背景
当前社会各行业领域竞争压力非常大,随着当前时代的信息化,科学化发展,让社会各行业领域都争相使用新的信息技术,对行业内的各种相关数据进行科学化,规范化管理。这样的大环境让那些止步不前,不接受信息改革带来的信息技术的企业随时面临被淘汰,被取代的风险。所以当今,各个行业领域,不管是传统的教育行业,餐饮行业,还是旅游行业,医疗行业等领域都将使用新的信息技术进行信息革命,改变传统的纸质化,需要人手工处理工作事务的办公环境。软件信息技术能够覆盖社会各行业领域是时代的发展要求,各种数据以及文件真正实现电子化是信息社会发展的不可逆转的必然趋势。本超市购物系统也是紧跟科学技术的发展,运用当今一流的软件技术实现软件系统的开发,让员工信息完全通过管理系统实现科学化,规范化,程序化管理。从而帮助信息管理者节省事务处理的时间,降低数据处理的错误率,对于基础数据的管理水平可以起到促进作用,也从一定程度上对随意的业务管理工作进行了避免,同时,超市购物系统的数据库里面存储的各种动态信息,也为上层管理人员作出重大决策提供了大量的事实依据。总之,超市购物系统是一款可以真正提升管理者的办公效率的软件系统。
关键技术
SpringBoot是一个全新开源的轻量级框架。基于Spring4.0设计,其不仅继承了Spring框架原来有的优秀特性,而且还通过简化配置文件来进一步简化了Spring应用的整个搭建以及开发过程。另外在原本的Spring中由于随着项目的扩大导入的jar包数量越来越大,随之出现了jar包版本之间的兼容性问题,而此时SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性问题得到了很好的解决。
JS-SDK是对之前的 WeixinJSBrige 的一个包装,以及新能力的释放,并且由对内开放转为了对所有开发者开放,在很短的时间内获得了极大的关注。从数据监控来看,绝大部分在微信内传播的移动网页都使用到了相关的接口。
JS-SDK 解决了移动网页能力不足的问题,通过暴露微信的接口使得 微信小程序 开发者能够拥有更多的能力,然而在更多的能力之外,JS-SDK 的模式并没有解决使用移动网页遇到的体验不良的问题。用户在访问网页的时候,在浏览器开始显示之前都会有一个的白屏过程,在移动端,受限于设备性能和网络速度,白屏会更加明显。我们团队把很多技术精力放置在如何帮助平台上的微信小程序开发者解决这个问题。因此我们设计了一个 JS-SDK 的增强版本,其中有一个重要的功能,称之为“微信 微信小程序 资源离线存储”。
JAVA语言是目前软件市场上应用最广泛的语言开发程序。可以在多种平台上运用的,兼容性比较强,适应市面上大多数操作系统,不会出现乱码的现像,其扩展性和维护性都更好,具有分析问题和解决问题的能力,是面向过程的程序设计方便我们编写的代码更强壮。
Vue是一款流行的开源JavaScript框架,用于构建用户界面和单页面应用程序。Vue的核心库只关注视图层,易于上手并且可以与其他库或现有项目轻松整合。
MYSQL数据库运行速度快,安全性能也很高,而且对使用的平台没有任何的限制,所以被广泛应运到系统的开发中。MySQL是一个开源和多线程的关系管理数据库系统,MySQL是开放源代码的数据库,具有跨平台性。
B/S(浏览器/服务器)结构是目前主流的网络化的结构模式,它能够把系统核心功能集中在服务器上面,可以帮助系统开发人员简化操作,便于维护和使用。
系统分析
对系统的可行性分析以及对所有功能需求进行详细的分析,来查看该系统是否具有开发的可能。
系统设计
功能模块设计和数据库设计这两部分内容都有专门的表格和图片表示。
系统实现
商品管理页面,提供给管理员的功能有:查看商品列表,新增商品,修改商品,删除商品。公告管理页面,提供给管理员的功能有:新增公告,修改公告,删除公告。公告类型管理页面,提供给管理员的功能有:新增公告类型,修改公告类型,删除公告类型。
系统测试
程序软件一旦被开发完成之后,在真正投入日常生活中进行运行使用之前,是必须要经历测试这一个重要的操作环节,因为开发期间注重的是每个单独功能模块的开发,尽管每次开发完成一个单独功能模块时,会通过单元测试进行检验,检验合格才会让程序员继续开发下一个子功能模块,以此类推,当程序员完成所有的系统子功能模块的开发时,这个时候就需要引进系统测试,系统测试就是把所有的子功能模块集成到一起,构建成整个系统,在指定的运行环境下进行运行,主要就是测试系统的所有功能模块在一起是否良好运行,一旦程序软件通过了系统测试这一环节,就意味着它可以进行最终的验收测试了,这个测试步骤的操作用户是程序面向的客户或者是最终用户了。
结论
通过对超市购物系统的开发,让我深刻明白开发一个程序软件需要经历的流程,当确定要开发一个超市购物系统的程序时,我在开发期间,对其功能进行合理的需求分析,然后才是程序软件的功能的框架设计,数据库的实体与数据表设计,程序软件的功能详细界面实现,以及程序的功能测试等进行全方位的细致考虑,虽然在此过程中,各个环节都遇到了大大小小的困难,但是通过对这些问题进行反复的分析,深入的思考,借助各种相关文献资料提供的方法与解决思路成功解决面临的各个问题,最后成功的让我开发的超市购物系统得以正常运行。
(可运行源码+sql文件+文档)
目录 1.创建表1.基本语法2.创建表案例 2.查看表结构3.修改表1.语法2.示例3.modify和change区别 4.删除表 1.创建表 1.基本语法 语法: CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎; 说明: field:表示列名datatype:表示列的类型character set:字符集,如果没有指定字符集,则以所在数据库的字符集为准collate:校验规则,如果没有指定校验规则,则以所在数据库的校验规则为准 2.创建表案例 create table Users ( id int, name varchar(20) comment '用户名', password char(32) comment '密码', birthday date comment '生日' ) character set utf8 engine InnoDB; 说明:不同的存储引擎,创建表的文件不一样 存储引擎是MyISAM,在数据目中有三个不同的文件 Users.frm:表结构Users.MYD:表数据Users.MYI:表索引 存储引擎是InnoDB,在数据目中有两个不同的文件 Users.frm:表结构Users.idb:表数据&表索引 2.查看表结构 语法: desc db_name; 3.修改表 在项目实际开发中,经常修改某个表的结构,比如字段名字,字段大小,字段类型,表的字符集类型, 表的存储引擎等等。可能还有需求,添加字段,删除字段等等。这时就需要修改表 1.语法 ALTER TABLE tablename ADD (column datatype [DEFAULT expr][,column datatype].
文章目录 需求实验修改dhcp虚拟机配置文件测试PC获取IP查看user-bind 需求 (vmware虚拟机充当DHCP服务器)所有IP全部保留,只为已知mac分配固定IP
实验 前期配置:
https://blog.csdn.net/xzzteach/article/details/140406092
后续配置均在以上配置的前提下完成:
修改dhcp虚拟机配置文件 vim /etc/dhcp/dhcpd.conf # dhcpd.conf # # Sample configuration file for ISC dhcpd # option domain-name "j.com"; #option domain-name-servers ns1.example.org, ns2.example.org; option domain-name-servers 192.168.200.113, 192.168.200.114; default-lease-time 600; max-lease-time 7200; log-facility local7; ###网段声明 subnet 192.168.5.0 netmask 255.255.255.0 { #range dynamic-bootp 192.168.5.51 192.168.5.199; #ip地址池【注注释掉】 #option domain-name-servers ns1.internal.example.org; #option domain-name "internal.example.org"; option routers 192.168.5.254; # 为客户端设定默认网关 option broadcast-address 192.168.5.255; #为客户端设定广播地址 #default-lease-time 600; #max-lease-time 7200; } ###网段声明 subnet 192.
单例模式是设计模式中的一种,它的核心思想是确保一个类在整个应用程序中只存在一个实例,并提供一个全局访问点来获取这个实例。
这在需要控制资源访问、节省系统开销或者协调共享状态的场景下特别有用,比如配置管理器、线程池和数据库连接池等。
单例模式的几种实现方式 在Java中,实现单例模式有多种方式,但核心目标都是确保实例的唯一性。其中,线程安全是实现过程中必须考虑的重要因素,尤其是在多线程环境下。以下是几种常见的实现方式及其线程安全讨论:
1. 饿汉式(静态常量/静态代码块) 特点:类加载时立即创建实例,线程安全,但可能导致资源浪费。
1public class Singleton { 2 private static final Singleton INSTANCE = new Singleton(); 3 4 private Singleton() {} 5 6 public static Singleton getInstance() { 7 return INSTANCE; 8 } 9} 线程安全分析:由于实例是在类加载时由JVM保证线程安全地初始化,因此这种方式天然线程安全。 2. 懒汉式(线程不安全) 特点:延时加载,但在多线程环境下可能创建多个实例。
1public class Singleton { 2 private static Singleton instance; 3 4 private Singleton() {} 5 6 public static Singleton getInstance() { 7 if (instance == null) { 8 instance = new Singleton(); 9 } 10 return instance; 11 } 12} 线程安全分析:在多线程环境下,如果有多个线程几乎同时进入getInstance()方法,都可能发现instance为null,进而各自创建实例,破坏了单例。因此,这种方式在多线程环境下是线程不安全的。 3.
7-4、5、6 react+ipfs上传文件数据及相关配置(react+区块链实战) 7-4 react+ipfs上传文件7-5 react+ipfs 上传数据+ipfs跨域配置7-6 react+ipfs读取ipfs网络数据 7-4 react+ipfs上传文件 引入之前安装的ipfs-api
在电脑后台启动ipfs的服务
ipfs daemon(这个是go-api的不使用)
这里直接使用jsipfs进行后台服务启动
发现版本不兼容,之前还可以启动来,这估计是新安装ipfs-desktop导致的
jsipfs daemon(使用js的版本可以启动)
一个是0.8.0版本的
一个是0.6版本的
这里没有卸载ipfs桌面版,在重启电脑后启动jsipfs daemon就能打开js的ipfs服务了
如果出现了某个模块未安装的情景
关闭start
执行
Npm install
执行npm start后结果应如下
此处是上传文本的,也可以改成上传文件的按钮
文本上传之后会显示哈希值显示在页面
我们可以将文本读取
上方未做值的拼接先不用
显示不是一串字符故下方
使用下方
handleClick(){
console.log(this.state.text)
}
<input value={this.state.text} onChange={(e)=>{
this.setState(
{text:e.target.value}
)
}}/>
上方input将value输入的值保存到state状态中的text中,点击提交时,会调用打印
将状态state中的text打印出来如下
//将input中的内容保存到ipfs上 saveTextToIpfs(text){ //要将其转换成buffer上传 const descBuf = Buffer.from(text,'utf-8') ipfs.add(descBuf).then(res=>{ console.log(res) }) } handleClick(){ this.saveTextToIpfs(this.state.text) //console.log(this.state.text) //打印保存到状态中的text值 } 值浏览器刷新看到有报错(预料之中的报错,由于跨域导致的)
预料之中的报错,由于跨域导致的
第一个错误跨域导致的
第二个错误是逻辑问题
想向5001端口发送,但是我们现在的本地端口是在3000,需要在ipfs之上进行跨域配置(下节课讲)
本节所有代码
import React from 'react'; import ipfsAPI from 'ipfs-api'; let ipfs = ipfsAPI('localhost','5001',{protocol:'http'}) //本地启动服务默认5001端口 class App extends React.
使用helm部署应用 Helm 是一个 Kubernetes 的包管理工具,用于简化应用的部署和管理。下面是用helm在k8s上部署应用的一般流程。
添加helm仓库 # 添加仓库 root@master1:~# helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts root@master1:~# helm repo add bitnami https://charts.bitnami.com/bitnami # 更新 root@master1:~# helm repo update Hang tight while we grab the latest from your chart repositories... ...Successfully got an update from the "aliyun" chart repository ...Successfully got an update from the "harbor" chart repository ...Successfully got an update from the "gitlab-jh" chart repository ... # 仓库列表 root@master1:~# helm repo list NAME URL ingress-nginx https://kubernetes.
百日筑基第二十天-一头扎进消息队列3-RabbitMQ 如上图所示,RabbitMQ 由 Producer、Broker、Consumer 三个大模块组成。生产者将数据发送到 Broker,Broker 接收到数据后,将数据存储到对应的 Queue 里面,消费者从不同的 Queue 消费数据。
那么除了 Producer、Broker、Queue、Consumer、ACK 这几个消息队列的基本概念外,它还有 Exchange、Bind、Route 这几个独有的概念。
Exchange 称为交换器,它是一个逻辑上的概念,用来做分发,本身不存储数据。流程上生产 者先将消息发送到 Exchange,而不是发送到数据的实际存储单元 Queue 里面。然后 Exchange 会根据一定的规则将数据分发到实际的 Queue 里面存储。这个分发过程就是 Route(路由),设置路由规则的过程就是 Bind(绑定)。即 Exchange 会接收客户端发送 过来的 route_key,然后根据不同的路由规则,将数据发送到不同的 Queue 里面。
这里需要注意的是,在 RabbitMQ 中是没有 Topic 这个用来组织分区的逻辑概念的。 RabbitMQ 中的 Topic 是指 Topic 路由模式,是一种路由模式,和消息队列中的 Topic 意义 是完全不同的。
协议和网络模块 RabbitMQ 在协议内容和连接管理方面,都是遵循 AMQP 规范。即 RabbitMQ 的模型架构 和 AMQP 的模型架构是一样的,交换器、交换器类型、队列、绑定、路由键等都是遵循 AMQP 协议中相应的概念。
RabbitMQ 的网络层有 Connectoion 和 Channel 两个概念。
Connection 是指 TCP 连接,Channel 是 Connection 中的虚拟连接。两者的关系是:一个 客户端和一个 Broker 之间只会建立一条 TCP 连接,就是指 Connection。Channel(虚拟连 接)的概念在这个连接中定义,一个 Connection 中可以创建多个 Channel。
1.内存可见性
当一个变量被声明volatile时,它会保证被修改的值被立刻更新到主内存中,不会优化到寄存器或缓存中
2.禁止指令重排序
针对被volatile修饰的变量的读写相关指令,是不能被重新排序的
代码演示 class Counter{ public int flag; } public class Thread3 { public static void main(String[] args) throws InterruptedException { Counter counter=new Counter(); Thread t1=new Thread(()->{ while (counter.flag==0){ //方便演示什么都不做 } }); Scanner scanner=new Scanner(System.in); Thread t2=new Thread(()->{ counter.flag=scanner.nextInt(); }); t1.start(); t2.start(); t1.join(); t2.join(); } } 上述代码,t1线程在循环检查flag值,成立就执行代码,t2线程更改count值,使得线程1检查结果不成立,测试发现在t2线程代码输入结果后,线程1代码还是不会停止,这是由于t1线程在一个无限循环中检查flag的值,并且flag的更新对t1线程不可见,因此t1线程可能会永远等待下去,即使t2线程已经修改了flag的值。
使用volatile解决 class Counter{ public volatile int flag; // 声明为 volatile } public class Thread3 { // ... 其他代码保持不变 ... } 使用volatile后