作者 | JiekeXu
来源 |公众号 JiekeXu DBA之路(ID: JiekeXu_IT)
如需转载请联系授权 | (个人微信 ID:JiekeXu_DBA)
大家好,我是 JiekeXu,江湖人称“强哥”,荣获 Oracle ACE Pro 称号,墨天轮 MVP,墨天轮年度“墨力之星”,拥有 Oracle 11g OCP/OCM 认证,MySQL 5.7/8.0 OCP 认证以及 PCA、PCTA、OBCA、OGCA、KCP 等众多国产数据库认证证书,今天和大家一起来看看关于 Oracle RAC 环境下 Apache Tomcat 漏洞(CVE-2024-21733)的解决方案,欢迎点击最上方蓝字“JiekeXu DBA之路”关注我的微信公众号,然后点击右上方三个点“设为星标”顶,更多干货文章才能第一时间推送,谢谢!
前 言 Apache Tomcat® 软件是一个开源实现 Jakarta Servlet、Jakarta Pages、Jakarta Expression Language、Jakarta WebSocket、Jakarta Annotations 和 Jakarta Authentication 规范。这些规格是 Jakarta EE 平台的一部分。
Jakarta EE 平台是 Java EE 平台的演进。Tomcat 10 及以后的版本实现了作为 Jakarta EE 一部分开发的规范。Tomcat 9 和更早版本的实现规范是作为 Java EE 的一部分开发的。目前,Apache Tomcat 项目自豪地宣布发布版本 10.
134. 加油站 全局思考:总油量减去总消耗大于等于零那么一定可以跑完一圈,局部贪心:累加每个站的净胜油量,如果<0,则在此之前(包括该站)都不是起始位置,从下一个位置开始寻找 class Solution { public: int canCompleteCircuit(vector<int>& gas, vector<int>& cost) { int cursum = 0, totalsum = 0; int start = 0; for (int i = 0; i < gas.size(); i++) { cursum += gas[i] - cost[i];//累加油量净剩量 totalsum += gas[i] - cost[i]; if (cursum < 0) {//i位置之前一定不满足 start = i + 1;//从i下一个位置开始重新寻找 cursum = 0; } } if (totalsum < 0)//总油量大于消耗的,所以肯定不能跑一圈 return -1; return start; } }; 135.
从零入门AI生图原理&实践 是 Datawhale 2024 年 AI 夏令营第四期的学习活动(“AIGC”方向),基于魔搭社区“可图Kolors-LoRA风格故事挑战赛”开展的实践学习。
Datawhale官方的速通教程链接:
Task 1 从零入门AI生图原理&实践
Datawhale(Task2)
下面是根据教程实践的记录
Part1:AI生图技术能力及局限 ①通俗来说,AI生图模型获得图片生成能力主要是通过 学习 图片描述 以及 图片特征,尝试将这两者进行一一对应,存储在自己的记忆里。
模型根据我们输入的文字+凭借它的能力→生成我们需要的图片
②不同模型用于训练的数据有限且不一定相同→匹配的描述和特征也是有限的
所以不同模型在风格和具体事物上会有很大的生成差异,且存在诸多于现实不符的情况
③关于“ai味”辨别方法:
*观察图片的细节(人物面部特征,特别是眼睛和嘴巴)
*检查光线和阴影(光源是否一致,阴影是否与光源相符,光线阴影会不会不正常)
*分析像素(是否有模糊/像素化部分)
*注意背景(是否有不协调eg.边缘是平滑,有无不自然的重复)
Part2:AI生图前沿探索 可以从魔搭社区各种AIGC开始探索 →魔搭社区
通过task1的学习,觉得数据集很重要!可以在魔搭开源数据集中寻找我们要的数据集
Kolors(可图)模型(点击即可跳转魔搭模型介绍页) 是快手开源的文本到图像生成模型,该模型具有对英语和汉语的深刻理解,并能够生成高质量、逼真的图像。以下是一些相关链接:
代码开源链接:https://github.com/Kwai-Kolors/Kolors
模型开源链接:https://modelscope.cn/models/Kwai-Kolors/Kolors
技术报告链接:https://github.com/Kwai-Kolors/Kolors/blob/master/imgs/Kolors_paper.pdf
魔搭研习社最佳实践说明:https://www.modelscope.cn/learn/575?pid=543
可图区别过去SD系列基础模型的一个特点是它支持中文文生图,
魔搭社区还开源了专门的各种风格的可图优质咒语书(点击即可跳转),可以针对600+种不同风格,完善prompt,生成各种风格图片
Part3:通过魔搭社区持续探索AI生图前沿 目前让ai稳定生成相似效果的海报还是比较困难,一些创意海报工具(eg.
创意海报生成 )往往是通过固定文字位置及字体进行相应海报生成,
大致是①ai生成背景②通过代码将对应的文字显示到对应位置,然后渲染合成照片输出给我们
自己想多多探索的话可以往这些方向思考
可以用在哪些业务里?有哪些行业在使用?用的是哪个 AI 模型?是自己部署的AI模型,还是用的API?使用到了哪些 AI 能力?如果要复现,需要做哪些额外的设置和开发?还可以有哪些优化点? 可以在刚刚的创意海报生成空间文件里进行相关代码的查看/下载到本地/云服务器复现,验证思考及学习相关的设计开发
一、认识通义千问 通义千问(点击直达)。
它相当于一个AI助手
二、使用这样一个AI助手帮我们精读baseline——①分析代码的主体架构②逐行代码解析 根据教程里图片可以直观感知文生图代码的框架结构
使用AI助手前我们先整理出baseline里所有的代码
!pip install simple-aesthetics-predictor !pip install -v -e data-juicer !pip uninstall pytorch-lightning -y !
2.1 进程线程区别 进程是资源分配的基本单位,线程是资源调度的基本单位每个进程有自己的私有地址空间、私有栈、堆,上下文切换需要切换虚拟地址空间线程之间公有一个地址空间、公有堆,但是栈和程序计数器是私有的,用来保存线程的执行历史和执行状态,上下文切换只需要切换少量寄存器 2.2 进程间通信方式 匿名管道: 只能在父子进程中使用pipe函数创建,在内核中创建一个环形队列作为缓冲区,兵返回两个文件描述符,一个用于读(fd[0]),一个用于写(fd[1])一个进程写数据就是写到内核缓冲区中,另一个进程可以从缓冲区中读取数据单向的,数据只能在一个方向上流动。如果需要双向通信必须创建两个管道 命名管道: 可以使用mkfifo函数创建,在文件系统中有一个对应的文件名可以通过文件名访问使用文件操作函数read、write来读写命名管道支持双向通信和跨网络通信,多个进程可以连接到同一个命名管道进行读写操作 消息队列: 独立于进程存在,当进程向消息队列发送消息时,会被存储在内核空间,直到其他进程从队列中读取允许异步通信,克服了管道缓冲区大小受限、只能承载无格式字节流的问题 共享内存: 允许多个进程访问同一块内存区域,从而实现进程间数据共享是最快的通信方式,避免了数据拷贝,但需要解决并发访问和同步的问题,同步机制包括互斥锁、信号量和事件等互斥锁要在全局命名空间中创建,这样能让多个不同的进程能够识别并访问同一个互斥锁 信号量: 用于多进程对共享资源访问的同步机制,P操作代表申请资源,V操作代表释放资源信号量也要使用全局命名空间 套接字: 网络通信接口,支持TCP/UDP等多种协议,一个进程作为服务器(监听套接字),另一个进程作为客户端(连接套接字) 信号: 允许一个进程向另一个进程发送信号;信号可以由多种原因产生,包括用户操作、硬件异常以及程序显式请求等是一种异步通信方式通过kill函数或raise函数发送信号(kill是发给另一个进程,raise是发给自己信号),当信号发送到进程时,会通过中断并调用相应的信号处理函数,可以使用signal函数处理 2.3 线程间通信方式 共享内存消息队列:可以实现线程间解耦合,使得线程之间不需要直接访问对方的内存空间同步对象:如信号量、条件变量等原子操作future和promise:允许一个线程向另一个线程传递异步计算的结果 promise用于设置一个可由future检索的结果,future提供了一种阻塞或非阻塞的方式获取结果 2.4 锁和死锁 两个基础锁:互斥锁和自旋锁 互斥锁:用于实现互斥访问共享资源,任何时刻只有一个线程可以持有互斥锁自旋锁:基于忙等待的锁,线程通过不断轮询尝试获取锁直到锁被释放 其他锁都是基于以上两个锁: 读写锁:分为共享和排他,允许多个线程同时读共享资源,只允许一个线程进行写操作悲观锁:多线程同时修改共享资源的概率比较高,所以访问共享资源时就要上锁乐观锁:多线程访问共享资源时不上锁,如果出现同时修改资源的情况就放弃本次操作 死锁:多个进程在运行时因争夺资源而造成的一种僵局,占有自身资源并请求对方资源 产生死锁的四个必要条件: 一段时间某资源仅能被一个进程占用对已获得的资源保持不放获得资源后不可被剥夺存在环形链 解决方式: 预防死锁:一次性分配所有资源、如果一个进程有部分资源得不到那么其他资源也不分配给他、如果一个进程获得了部分资源但得不到其他资源就会主动释放获得的资源、给资源设定编号每个进程按编号递增顺序请求资源避免死锁:银行家算法检测死锁:建立资源分配图、判断是否有环路解除死锁:进程回滚、剥夺资源、终止进程鸵鸟策略:死锁发生的概率很低的时候假装没发生死锁,因为要解决死锁的代价很高 2.5 Linux的内核设计理念 多任务:多个任务同时执行。单核CPU时间轮询方式并发执行,多核CPU多个任务同时在不同CPU上并行执行对称多处理SMP:每个CPU的地位是相等的,对资源的使用权限也是相同的,多个CPU共享同一内存可执行文件链接格式ELF:Linux操作系统中可执行文件的存储格式宏内核: Linux的内核是一个完整的可执行程序,且拥有最高的权限 2.6 虚拟内存的作用和实现方式 虚拟地址可以把进程所使用的地址隔离开,进程间互不干涉操作系统引入虚拟内存,进程持有的虚拟地址通过MMU的映射关系转换成物理地址,物理地址访问内存操作系统管理虚拟地址和物理地址的关系的方法:内存分段和分页 2.7 分段、分页、段页式 分段: 程序由代码段、数据段、栈段、堆段4个部分组成,将不同的段用分段的形式分离开分段机制下,虚拟地址由段选择因子和段内偏移量组成。段选择因子里的段号用作段表的索引,段表保存了段的基地址、段的界限和特权等级等;段内偏移量位于0和段界限之间段基地址+段内偏移量 = 物理地址 分页: 把整个虚拟内存和物理内存切成一段段固定尺寸的大小,称为一页,每页4KB页表存储在内存里,通过MMU将虚拟内存地址转换为物理地址,如果进程访问虚拟地址在页表中查不到会产生缺页异常分页机制下,虚拟地址分为页号和页内偏移。页号作为页表的索引,页表包含物理页每页所在的物理内存的基地址,基地址+页内偏移 = 物理地址一开始是单页表,为了减小内存占用,产生多级页表,如果某个一级页表没有被用到也就不需要再内存中创建对应的二级页表了;为了降低时间开销,引入页表缓存,也叫TLB,利用程序的局部性原理,把最常访问的几个页表存储到缓存中 段页式: 先将程序划分为多个段,再把每个段划分为多个页,地址结构由段号、段内页号和页内偏移组成,每个程序一张段表,每个段有一张页表,段表中的地址是页表的起始地址,页表中的地址是某页的物理页号要得到物理地址需要经过三次内存访问: 访问段表,得到页表起始地址访问页表,得到物理页号将物理页号与页内偏移组合,得到物理地址 2.8 Linux内存管理 程序所使用的地址称为逻辑地址,通过段式内存管理映射成线性地址,也叫虚拟地址,再由页式内存管理映射成物理地址 2.9 用户态和内核态的区别 主要是为了提高系统的稳定性、安全性和性能,在这两种状态下,处理器对资源的访问权限不同用户态只能访问受限资源,无法修改硬件配置等,主要是防止用户程序对系统关键资源的非法访问内核态可以访问系统的所有资源,包括资源分配、进程调度等核心功能用户态通过系统调用、异常或中断进入内核态,而内核态设置程序状态字返回用户态 2.10 中断 中断指CPU暂停正在执行的程序,保存现有程序的上下文然后去执行相应的处理程序,处理完再返回中断处继续执行原来的程序中断分为软中断、硬中断(外部中断)、内部中断 软中断是由程序的指令触发的中断,比如说系统调用,是不能被屏蔽的硬中断是由CPU外部引起的,比如IO中断、时钟中断等,可以屏蔽内部中断是由CPU或其他硬件生成的信号,例如浮点运算溢出、除零错误等 中断保存的东西存放在栈中中断处理包括中断请求、中断判优、中断响应(从多个CPU中断请求中选择一个优先级最高的)、中断服务和中断返回五个阶段 2.11 静态链接、动态链接,静态链接库、动态链接库 静态链接:编译链接时将代码拷贝到调用出 代码运行速度快,但是会浪费空间 动态链接:代码在需要的时候才会加载到内存,多个程序调用一个代码时可以共享内存 运行时加载,速度慢 静态链接库:在程序编译时,将库直接链接到最终的可执行文件中 一旦可执行文件被创建就包含了库的所有数据不再需要库文件支持即可独立运行,但生成的可执行文件较大,库中数据被多次复制,且库更新需要重新编译 动态链接库:在程序运行时,库的数据被加载到内存中,而不是链接到可执行文件中 程序更加模块化和可移植,但会增加程序的运行时间 2.
博主主页:猫头鹰源码
博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万+、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作
主要内容:毕业设计(Javaweb项目|小程序|Python|HTML|数据可视化|SSM|SpringBoot|Vue|Jsp|PHP等)、简历模板、学习资料、面试题库、技术咨询
文末联系获取
感兴趣可以先收藏起来,以防走丢,有任何选题、文档编写、代码问题也可以咨询我们
项目介绍: 该系统为原创项目,创作于2024年,课题为山东旅游,可以改为其它地方的旅游。项目有基于springboot和ssm两个技术版本,数据层为MyBatis,mysql数据库,具有完整的业务逻辑,适合选题:山东、旅游推荐、旅游、旅游路线、Java项目、javaweb等。
项目功能: 系统共分为用户,管理员两种角色 管理员:1.新增用户的时候,可以实现增删改查;2.登陆界面可以实现登录以及用户注册 用户:1.登陆界面可以实现登录以及用户注册 管理员: 用户管理:新增,修改,查看,删除查看用户的信息 旅游路线管理:新增路线,修改,查看,删除 旅游景点管理:新增景点,修改,查看,删除 旅游攻略管理:新增攻略,修改,查看,删除 酒店管理:新增景点,修改,查看,删除 评论管理:评论维护 留言管理:查看,删除 用户: 旅游路线管理:查看路线,评论 推荐路线:根据评论采用基于用户的协同过滤算法进行推荐 旅游景点:查看景点信息 旅游攻略:查看攻略信息 酒店:搜索酒店,查看酒店信息,预约酒店 我的留言:填写留言,提交 我的评论:查看我的评论信息 用户:查看个人信息、填写个人信息、修改个人信息 、修改密码 系统包含技术: 后端:springboot和ssm两个版本都有
前端:layui、bootstrap、js、css等
开发工具:idea
数据库:mysql 5.7
JDK版本:jdk1.8
语言:Java语言
是否Maven:是
页面类型:html
部分截图说明: 首页
景点
景点详情
旅游攻略
攻略详情
酒店详情
用户管理
景点管理
旅游路线管理
部分代码: /**进入列表页面*/ @GetMapping("/hotel") public String userIframe(Model model){ return "HotelList"; } /**列表数据*/ @GetMapping("/list") @ResponseBody public PageResultVo findHotel(Hotel hotel, Integer limit, Integer page){ PageHelper.
文章目录 设计模式反模式:UML常见误用案例分析1. 反模式概述2. 反模式的 UML 图示误用2.1 God Object 反模式2.2 Spaghetti Code 反模式2.3 Golden Hammer 反模式2.4 Poltergeist 反模式 3. 总结 设计模式反模式:UML常见误用案例分析 在软件工程领域,设计模式是解决特定问题的成熟模板,它们促进了代码的可维护性和可扩展性。然而,设计模式如果被误用或滥用,就可能演变为反模式,导致软件设计出现缺陷。本文将探讨一些常见的设计模式反模式,尤其是在UML图示中的误用,并提供C#示例进行阐述。
1. 反模式概述 反模式通常指那些表面上看似合理,但实际上会带来负面效果的设计或实践。它们经常是由于对设计模式的错误应用或理解不足造成的。一些常见的设计模式反模式包括:
God Object:一个类承担了过多的职责。Spaghetti Code:代码结构混乱,缺乏清晰的模块划分。Golden Hammer:对某一种解决方案的过度依赖。Poltergeist:存在几乎没有实际功能的类或对象。 2. 反模式的 UML 图示误用 2.1 God Object 反模式 误用案例: 在UML类图中,所有功能和数据集中在一个类中。
public class ApplicationManager { public void LoadData() { /* ... */ } public void SaveData() { /* ... */ } public void ProcessData() { /* ... */ } public void PrintReport() { /* .
一、ConfigMap资源配置 ConfigMap保存的是不需要加密配置的信息
ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API 给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象。
应用场景:应用配置
创建 ConfigMap 方法1: 只要指定为一个文件就可以从单个文件中创建 ConfigMap --from-file 这个参数可以使用多次,即可以使用两次分别指定上个实例中的那两个配置文件 --from-file 指定在目录下的所有文件都会被用在 ConfigMap 里面创建一个键值对,键的名字就是文件名,值就是文件的内容 kubectl create cm demo1-cm --from-file=demo/ 方法2: 使用文字值创建,利用 --from-literal 参数传递配置信息 kubectl create cm kv-cm --from-literal=myname=kukun --from-literal=mylove=hobby Pod 中使用 ConfigMap 作为数据卷挂载使用 vim demo1-pod.yaml apiVersion: v1 kind: Pod metadata: creationTimestamp: null labels: run: demo-pod name: demo-pod spec: volumes: - name: cm-vol #定义存储卷名称 configMap: name: demo-cm #指定cm资源名称 containers: - image: soscscs/myapp:v1 name: myapp ports: - containerPort: 80 resources: {} volumeMounts: #指定挂载容器信息 - name: cm-vol mountPath: /mnt dnsPolicy: ClusterFirst restartPolicy: Always status: {} 作为环境变量引用使用 vim demo2-pod.
引言 在这个数字化转型的时代,微服务架构已经成为构建现代应用程序的首选方式。它不仅提高了开发效率,还增强了系统的可扩展性和灵活性。而随着云计算技术的迅猛发展,云原生的概念逐渐深入人心,它代表了一种全新的软件开发方法论,旨在利用云基础设施的优势来构建和运行可伸缩的应用程序。在这一背景下,Kubernetes(简称K8s)作为容器编排领域的佼佼者,其重要性不言而喻。本文将深入探讨Kubernetes在微服务与云原生技术中的应用,通过一系列基础和高级实例,帮助你掌握Kubernetes集群管理的关键技能。
基础语法介绍 什么是Kubernetes? Kubernetes是一种开源系统,用于自动化部署、扩展以及管理容器化应用。它由Google于2014年创建,并由Cloud Native Computing Foundation (CNCF)维护。Kubernetes能够简化容器化应用的部署流程,提供强大的服务发现和负载均衡能力,同时支持自动回滚和滚动更新等高级功能。
核心概念 Pods:这是Kubernetes中最小的可部署单元。一个Pod可以包含一个或多个容器,这些容器共享存储资源和网络空间。Services:用于定义一组Pods的服务端点,使得这些Pods可以通过统一的网络地址被访问。Deployments:用于描述应用的期望状态。Kubernetes会持续确保当前状态与期望状态一致。Volumes:用于存储Pods的数据,即使Pods被销毁重建,数据仍然得以保留。Namespaces:用于对集群资源进行逻辑分组,便于资源管理和权限控制。 基本语法规则 使用kubectl命令行工具与Kubernetes集群交互。通过YAML或JSON文件定义资源。利用标签(labels)和选择器(selectors)来组织和查找资源。 基础实例 让我们通过一个简单的例子来了解如何使用Kubernetes部署一个简单的Web应用。
创建Deployment apiVersion: apps/v1 kind: Deployment metadata: name: webapp-deployment spec: replicas: 3 selector: matchLabels: app: webapp template: metadata: labels: app: webapp spec: containers: - name: webapp image: nginx:latest ports: - containerPort: 80 创建Service apiVersion: v1 kind: Service metadata: name: webapp-service spec: selector: app: webapp ports: - protocol: TCP port: 80 targetPort: 80 type: LoadBalancer 通过上述两个配置文件,我们可以轻松地部署一个包含三个副本的Nginx Web服务器,并通过LoadBalancer类型的Service暴露给外部访问。
一.高可用集群 1.1 集群类型 LB:Load Balance 负载均衡LVS/HAProxy/nginx(http/upstream, stream/upstream)HA:High Availability 高可用集群数据库、RedisSPoF: Single Point of Failure,解决单点故障HPC:High Performance Computing 高性能集群 1.2 系统可用性 SLA:Service-Level Agreement 服务等级协议(提供服务的企业与客户之间就服务的品质、水准、性能等方面所达成的双方共同认可的协议或契约) A = MTBF / (MTBF+MTTR)
1.3 系统故障 硬件故障:设计缺陷、wear out(损耗)、非人为不可抗拒因素 软件故障:设计缺陷 bug
1.4 实现高可用 提升系统高用性的解决方案:降低MTTR- Mean Time To Repair(平均故障时间)
解决方案:建立冗余机制
active/passive 主/备
active/active 双主
active --> HEARTBEAT --> passive
active <--> HEARTBEAT <--> active
1.5.VRRP:Virtual Router Redundancy Protocol 概述:
虚拟路由冗余协议,解决静态网关单点风险
利用VRRP,一组路由器(同一个LAN中的接口)协同工作,但只有一个处于Master状态,处于该状态的路由器(的接口)承担实际的数据流量转发任务。在一个VRRP组内的多个路由器接口共用一个虚拟IP地址,该地址被作为局域网内所有主机的缺省网关地址。
VRRP决定哪个路由器是Master,Master路由器负责接收发送至用户网关的数据包 并进行转发,以及响应PC对于其网关IP地址的ARP请求。
Backup路由器侦听Master路由器的状态,并在Master路由器发生故障时,接替其工作,从而保证业务流量的平滑切换。
物理层:路由器、三层交换机
软件层:keepalived
1.5.1 VRRP 相关术语 虚拟路由器:Virtual Router
目录
1. 线性表
2. 顺序表
2.1 概念与结构
2.2 分类
2.2.1 静态顺序表
2.2.2 动态顺序表
2.3 动态顺序表的实现
正文
1. 线性表 线性表( linear list )是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使 ⽤的数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储。 2. 顺序表 2.1 概念与结构 概念:顺序表是⽤⼀段物理地址连续的存储单元依次存储数据元素的线性结构,⼀般情况下采⽤数组存储。 顺序表和数组的区别? 顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝ 2.2 分类 2.2.1 静态顺序表 静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费 2.2.2 动态顺序表 2.3 动态顺序表的实现 先创建三个文件
如图:
在头文件(SeqList.h)中引入相应的头文件
在相应的源文件中引入头文件
第一步进行初始化和销毁代码的实现
在头文件中定义函数
在源文件中写函数方法
在测试文件中调用此方法,并调试
下面该插入数据 SeqList.h
在插入数据之前我们药判断顺序表中的空间是否充足 所以我们要写一个判断空间是否充足的函数
SeqList.h
SeqList.c
接下来是删除数据
SeqList.h
SeqList.c
接下来是在指定位置的插入数据/删除数据
先要找到指定位置才可之后的操作
SeqList.h
SeqList.c
附源码
SeqList.h
#pragma once #include<stdio.h> #include<stdlib.h> #include<assert.
Welcome to 9ilk's Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: 数据结构 本篇博客我们继续了解一些二叉树的进阶算法。
🏠 二叉搜索 树转化为双向循环链表 📌 题目内容 将二叉搜索树转化为排序好的双向循环链表
📌 题目解析 双向循环链表所连接的结点是有序的。题目要求原地转换,也就是说不允许新new结点形成新的链表,而是改变搜索树中结点指针指向。搜索树中结点的值都是唯一的,我们无需担心出现重复值结点。 📌 算法原理 ✏️ 思路一: 题目要求链表中的节点是排好序的,因此结合二叉搜索树的性质(二叉搜索树中序遍历出来是有序的),我们可以按照对二叉树进行中序遍历,然后依次将节点指针存进vector里,最后遍历vector将各个节点的前驱和后继指针给处理好,最后别忘记头节点前驱指向尾节点,尾节点后继指向头节点。
动图演示:
参考代码:
class Solution { public: void InOrder(Node* root,vector<Node*>& treev) //利用中序遍历 因为二叉搜索树中序是排好序的 { if(root == nullptr) return; InOrder(root->left,treev); treev.push_back(root); //存进数组 InOrder(root->right,treev); } Node* treeToDoublyList(Node* root) { if(root == nullptr) return root; vector<Node*> treev; InOrder(root,treev); int cur = 1 ; Node* prev = treev[0]; Node* del = treev[1]; while(cur < treev.
众所周知,如果所有者或其他人多次输入错误密码,iOS 会锁定并禁用 iPhone 或 iPad。Apple 推出了使用 iTunes/Finder、iCloud 或其他 iOS 设备解锁已禁用设备的方法。但是,每种方法都需要一些先决条件,例如 Apple 密码。在这种情况下,使用第三方免费iPhone/iPad 解锁器是进入锁定的 iOS 设备的另一种选择。以下是最佳列表。
6 款最佳免费 iOS 解锁器 1、奇客iOS解锁 作为最好的免费 iPhone 解锁软件之一,Apeaksoft iOS Unlocker适合初学者和高级用户。用户友好的界面让您轻松导航。此外,它可以在 iOS 设备上执行各种解锁工作。
优点
从 iPhone 或 iPad 上删除密码、Touch ID 和 Face ID。
无需密码即可从 iOS 设备中删除 Apple ID。
绕过屏幕时间密码而不丢失数据。
跳过 MDM 锁并摆脱 MDM 配置文件。
删除 iTunes 备份密码。
支持最新的iPhone和iPad型号以及最新的iOS版本。
缺点
免费试用后,您需要购买许可证。
来源:
一键擦除iPhone/iPad/iPod密码- 奇客手机解锁忘了iPhone/iPad/iPod密码?奇客手机解锁可以在不用密码的情况下,鼠标点击一下轻松移除锁屏进入iPhone/iPad/iPod。https://www.geekersoft.cn/geekersoft-anyunlock.html
2、AnyUnlock AnyUnlock 是一款可解锁 iPhone 或 iPad 的软件。如果您忘记了 Apple ID 密码、锁屏密码、屏幕使用时间密码或 iTunes 备份密码,它可以帮助您快速解锁设备。完整版起价为 39.
CentOS7系统上有一个MySQL8的数据库,使用mysqldump -uroot -p dbname > bak.sql 导出的文件有1.3G
现打算把它全量导入到同一个机器上的postgresql(使用yum安装的,版本为9.2)
网上能搜到的例子,大多是pgloader,实测执行pgloader mysql://xxx/dbname postgresql://xxx/dbname总是会报错,解决完一个又会有新的一个,折腾了好一会,最终参考了这个:https://stackoverflow.com/a/77281281/9586338
改用NMIG 之后,成功把数据导入了,大致步骤如下:
git clone https://github.com/AnatolyUss/nmig cd nmig npm ci npm run build # 编辑config/config.json npm run start
第2章 C语言基础知识 1.printf()函数 在控制台输出数据,需要使用输出函数,C语言常用的输出函数为printf()。
printf()函数为格式化输出函数,其功能是按照用户指定的格式将数据输出到屏幕上。
printf(“格式控制字符串”,[输出列表]);
格式控制字符串:指定输出格式,以%开头,%符号后面跟各种格式控制字符;格式控制字符串的具体形式: “%标志][宽度][.精度][长度]类型”,例如: %c、%d、%3d、%.6f ┄
(1)类型 printf()函数可以输出任意类型的数据,如整型、字符型、浮点型数据等。
格式控制字符含义s字符串c单个字符d有符号十进制整型u无符号十进制整型o无符号八进制整型x无符号十六进制整型小写X无符号十六进制整型大写f单精度/双精度浮点型(默认打印6位小数)e科学记数eE科学记数Ep变量地址 类型应用示例一:
printf("%c", 'H'); //以%c格式输出字符'H' printf("%s", "Hello, world!\n"); //以%s格式输出字符串"Hello, world!" printf("%d", 100); //以%d格式输出整数100 类型应用示例二:
printf("%d%d%d\n",1,2,3); //使用3个%d输出三个整数1、2、3 printf("%f\n%c\n",2.1,'a'); //使用%f与%c输出2.1与字符'a' (2)标志 printf()函数中的标志字符用于规范数据的输出格式,如左对齐、右对齐、空缺填补等,标志符有“-”“+”“0”“空格”“#”五种。
标志符含义-左对齐;printf()函数输出数据默认为右对齐+当一个数为正数时,前面加上一个+符号。默认正数不显示+符号0右对齐时,用0填充左边空缺。默认使用空格填充空格输出正数时,前面为空格;输出负数时,前面带-符号#对%c、%s、%d、%u等无影响;对%o格式,输出时加上八进制前缀0;对%x(%X)格式,输出时加上十六进制前缀0x (3)宽度 宽度是用十进制表示的输出数据的位数,若实际位数多于定义的宽度,则按实际位数输出;若实际位数少于定义的宽度则补以空格或0。
宽度应用示例一:
printf("%d\n", 123); //按实际位数3输出 printf("%5d\n", 123); //设置宽度为5 printf("%10d\n", 123); //设置宽度为10 宽度应用示例二:
printf("%d\n", 123); printf("%-5d\n", 123); //添加-符号,左对齐输出 printf("%010d\n", 123); //添加0,左边以0填充 (4)精度 精度格式以字符“.”开头,后面跟十进制整数,精度主要作用于浮点型数据,表示输出小数点后面的位数。
如果不设置精度,默认输出小数点后6位。如果作用于整型数据,则表示按照一定宽度输出数据,左侧空缺填充0。在使用精度时,如果实际位数大于所定义的精度数,则截去超出的部分。 精度应用示例:
printf("%f\n", 1.234567); //默认输出小数点后6位 printf("%.8f\n", 1.234567); //输出小数点后8位,后面填充0 printf("%.3f\n", 1.234567); //输出小数点后3位,截断超出的部分 printf("%.6d\n", 123); //输出123的宽度为6,左侧填充0 (5)长度 长度格式符包括h、l两种,h是short的简写,表示按短数据类型量输出;l是long的简写,表示按长数据类型输出。
最近在写自己的React项目,我在使用useRef钩子函数的时候发现
TS2322: Type MutableRefObject<HTMLDivElement | undefined> is not assignable to type LegacyRef<HTMLDivElement> | undefined Type MutableRefObject<HTMLDivElement | undefined> is not assignable to type RefObject<HTMLDivElement> Types of property current are incompatible. Type HTMLDivElement | undefined is not assignable to type HTMLDivElement | null Type undefined is not assignable to type HTMLDivElement | null index.d.ts(303, 9): The expected type comes from property ref which is declared here on type 这是我的代码:
const backgroundDOM = useRef<HTMLDivElement>(); 解决方法:
目录
存活、就绪和启动探针
存活探针(Liveness Probe)
就绪探针(Readiness Probe)
启动探针(Startup Probe)
检测方式:
exec:
HTTP GET:
TCP Socket:
grpc:
配置探针
配置存活探针:
定义存活探测命令:
定义一个存活态 HTTP 请求接口
定义 TCP 的存活探测
配置就绪探针
配置启动探针
探针的配置字段
存活、就绪和启动探针 存活探针(Liveness Probe) 存活探针决定何时重启容器。 例如,当应用在运行但无法取得进展时,存活探针可以捕获这类死锁。
如果一个容器的存活探针失败多次,kubelet 将重启该容器。
存活探针不会等待就绪探针成功。 如果你想在执行存活探针前等待,你可以定义 initialDelaySeconds,或者使用启动探针。
就绪探针(Readiness Probe) 就绪探针决定何时容器准备好开始接受流量。 这种探针在等待应用执行耗时的初始任务时非常有用,例如建立网络连接、加载文件和预热缓存。
如果就绪探针返回的状态为失败,Kubernetes 会将该 Pod 从所有对应服务的端点中移除,并且不会将该Pod的IP地址添加到对应Service的负载均衡池中,从而避免将流量路由到该容器。
就绪探针在容器的整个生命期内持续运行。
启动探针(Startup Probe) 启动探针检查容器内的应用是否已启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被 kubelet 杀掉。
如果配置了这类探针,它会禁用存活检测和就绪检测,直到启动探针成功为止。
这类探针仅在启动时执行,不像就绪探针那样周期性地运行。
检测方式: exec: 在容器内执行特定命令,根据命令的退出状态码来判断是否成功。如果命令返回状态码为0,则认为容器是健康的;否则,认为容器不健康。
HTTP GET: 对容器的IP地址上的指定端口和路径执行HTTP GET请求。如果响应的状态码在200-399之间,则认为容器是健康的。
TCP Socket: 检查容器的指定端口是否能够接受TCP连接。如果连接成功,则认为容器是健康的。
grpc: v1.27以上版本适用
通过gRPC协议与容器内的应用程序通信,并基于应用程序的响应来判断其是否健康。如"SERVING",Kubernetes会认为这次健康检查是成功的,并据此判断容器是健康的。
配置探针 配置存活探针: 定义存活探测命令: 创建pod并以 busybox 为基础镜像的yaml文件:
1. 创建订单
请求创建订单的 API 接口:把 订单金额、收货地址、订单中包含的商品信息 发送到服务器服务器响应的结果:订单编号 2.订单预支付
请求订单预支付的 API 接口:把步骤1得到的 订单编号 发送到服务器服务器响应的结果:订单预支付的参数对象,里面包含了订单支付相关的必要参数 3.发起微信支付
调用 wx.requestPayment() 这个 API,发起微信支付;把步骤2得到的 订单预支付对象 作为参数传递给 wx.requestPayment() 方法监听 wx.requestPayment() 这个API 的 success,fail,complete 回调函数 示例代码如下(注意:以下代码仅作为示例,实际使用时需要根据业务需求进行调整): // 1. 用户触发支付 async function onOrderClick() { const orderInfo = { // 这里填入你的订单信息 }; // 2. 调用后端提供的创建订单的 API 向服务端发起请求,将订单信息参数 orderInfo 传给服务端,服务端创建订单,并将订单编号返回给前端 const orderNumber = await getOrderNumber(orderInfo) // 3.调用后端提供的预支付订单的 API 向服务端发起请求,将拿到的订单编号传给服务端,来获取订单预支付参数 const prepayData= await getOrderPrepayData({orderNumber}) // 订单预支付参数具体如下: prepayData={ "timeStamp": "xxx", // 时间戳,精确到毫秒级 "
目录
1. 树型结构
概念
树的表示形式
编辑
2. 二叉树(重点)
2.1 概念
2.2 二叉树的性质
2.3 二叉树的存储
2.4 二叉树的遍历
前中后序遍历
层序遍历:
2.5二叉树的基本操作
本篇主要理解树和二叉树相关概念,二叉树遍历及基本操作。
1. 树型结构 树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点: 有一个特殊的结点,称为根结点,根结点没有前驱结点。除根结点外,其余结点被分成M(M > 0)个互不相交的集合T1、T2、......、Tm,其中每一个集合Ti (1 <= i <= m) 又是一棵与树类似的子树。每棵子树的根结点有且只有一个前驱,可以有0个或多个后继树是由递归定义的。 树与非树的区分点:
树形结构中,子树之间不能有交集,否则就不是树形结构树形结构中,除根结点外,每个节点有且仅有一个父节点,否则就不是树形结构树形结构中,一颗N个结点的树有N-1条边,否则就不是树形结构 1.1概念 树型结构里,有非常多的概念,多用用就记住了
结点的度 :一个结点含有子树的个数称为该结点的度; 如上图: A 的度为3 树的度 :一棵树中,所有结点度的最大值称为树的度; 如上图:树的度为3 叶子结点或终端结点 :度为 0 的结点称为叶结点; 如上图:J F K L 等节点为叶结点 双亲结点或父结点 :若一个结点含有子结点,则这个结点称为其子结点的父结点; 如上图: A 是 B 的父结点 孩子结点或子结点 :一个结点含有的子树的根结点称为该结点的子结点; 如上图: B 是 A 的孩子结点 根结点 :一棵树中,没有双亲结点的结点;如上图: A 结点的层次 :从根开始定义起,根为第 1 层,根的子结点为第 2 层,以此类推 树的高度或深度 :树中结点的最大层次; 如上图:树的高度为 4 树的以下概念只需了解,在看书时只要知道是什么意思即可: 非终端结点或分支结点 :度不为 0 的结点; 如上图: B 、 C 、 D 、 E.
负载均衡 nginx lvs haproxy 官网 https://www.haproxy.co m/ 自由及开放源代码软件 HAProxy是一个使用C语言编写的自由及开放源代码软件,其提供高可用 性、负载均衡,以及基于TCP和HTTP的应用程序代理。 HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保 持或七层处理。HAProxy运行在当前的硬件上,完全可以支持数以万计的并 发连接。并且它的运行模式使得它可以很简单安全地整合进用户当前的架构 中, 同时可以保护用户的web服务器不被暴露到网络上。 HAProxy实现了一种事件驱动, 单一进程模型,此模型支持非常大的并发连 接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的 锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时 间管理的用户空间(User-Space) 实现所有这些任务,所以没有这些问题。此 模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他 们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。 包括 GitHub、Bitbucket[3]、Stack Overflow[4]、Reddit、Tumblr、 Twitter[5][6]和 Tuenti[7]在内的知名网站,及亚马逊网络服务系统都使用 了HAProxy。1.安装 2.配置 [root@haproxy ~]# yum -y install ntpdate.x86_64 [root@haproxy ~]# yum -y install ntp [root@haproxy ~]# ntpdate cn.ntp.org.cn 13 Aug 19:39:27 ntpdate[1955]: adjust time server 120.197.116.202 offset 0.059032 sec [root@haproxy ~]# systemctl start ntpd [root@haproxy ~]# systemctl enable ntpd [root@haproxy ~]# yum -y install haproxy18.
在香港云服务器上优化网站性能可以通过以下几种方式进行,确保用户从全球各地访问时获得快速、稳定的体验:
1. 使用内容分发网络 (CDN)
优势:CDN可以将静态内容(如图像、视频、CSS、JavaScript文件)缓存到全球多个节点上,让用户从距离最近的节点获取数据,降低访问延迟。步骤:选择支持全球或区域分布的CDN服务(如Cloudflare、阿里云CDN)。配置域名DNS,设置CDN加速规则,优化缓存策略。 2. 启用浏览器缓存
优势:减少用户多次访问时的加载时间,尤其对于经常变化的内容,可以设置适当的缓存策略。步骤:通过在服务器上设置适当的HTTP头信息来控制缓存时间,减少重复请求。使用.htaccess文件(Apache)或配置nginx的缓存策略。 3. 启用Gzip或Brotli压缩
优势:压缩网页内容,使传输的数据量减少,从而加快页面加载速度。步骤:在服务器上启用Gzip压缩(对于Apache服务器)或Brotli压缩(对于nginx服务器),压缩HTML、CSS、JavaScript文件等内容。 4. 优化数据库查询
优势:减少数据库查询次数和复杂度,提高数据加载效率。步骤:使用缓存机制(如Memcached、Redis)来存储频繁请求的数据。优化数据库索引,避免慢查询,减少不必要的数据库请求。 5. 图片和文件的优化
优势:减少页面加载时间,提升用户体验。步骤:使用压缩工具(如TinyPNG、ImageOptim)优化图像大小。使用WebP格式图片,减少图像文件的大小而不损失质量。启用延迟加载(lazy loading)技术,只有当图像进入视窗时才加载。 6. 减少HTTP请求数
优势:减少浏览器需要发起的请求次数,从而加快页面加载。步骤:将CSS和JavaScript文件进行合并和最小化,减少不必要的空白和注释。将图片整合为精灵图(sprites)以减少单独的图像请求数。 7. 使用HTTP/2或HTTP/3协议
优势:HTTP/2和HTTP/3支持多路复用和头部压缩,可以大幅提升数据传输效率。步骤:确保服务器支持HTTP/2或HTTP/3协议,配置SSL/TLS证书,因为这两种协议通常要求HTTPS加密。 8. 优化服务器响应时间
优势:提升服务器处理请求的速度,降低用户感知的延迟。步骤:使用轻量级的Web服务器(如nginx)。增加服务器的CPU、内存等资源,确保有足够的处理能力。使用负载均衡,分担服务器的压力。 9. 使用合适的托管计划
优势:确保根据业务需求选择适当的服务器资源,避免资源不足或浪费。步骤:根据网站流量和资源需求,选择适合的云服务器方案。如果流量波动较大,考虑使用弹性伸缩服务,自动调整服务器资源。 10. 定期监控和优化性能
优势:及时发现性能瓶颈并调整配置,确保持续的优化。步骤:使用网站性能监控工具(如Google Lighthouse、GTmetrix)定期检查网站加载时间。使用服务器监控工具(如Zabbix、Prometheus)监控资源使用情况,并根据负载调整。 使用莱卡云服务器通过这些优化手段,你可以显著提升香港云服务器上的网站性能,确保在全球范围内提供快速稳定的访问体验。