Linux CGroup资源限制(概念限制进程CPU使用)
Linux CGroup资源限制(详解)
最近客户认为我们程序占用cpu过高,希望我们限制,排查之后发现是因为程序频繁gc导致,为了精细化、灵活的的限制,想到了使用Linux CGroup。
0 前置知识
①概念及作用
官网:https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html
Linux系统每个进程都可以自由竞争系统资源,有时候会导致一些次要进程占用了系统某个资源(如CPU)的绝大部分,主要进程就不能很好地执行,从而影响系统效率,重则在linux资源耗尽时可能会引起错杀进程。因此linux引入了linux cgroups来控制进程资源,让进程更可控。
- CGroup可以让进程更加的可控。相当于给你画了一个圈,你只能在这个圈里活动(受限制)。
- Linux Cgroup 可让我们为系统中所运行任务(进程)的用户定义组群分配资源,比如 CPU 时间、系统内存、网络带宽或者这些资源的组合。我们可以监控配置的 cgroup,拒绝 cgroup 访问某些资源,甚至在运行的系统中动态配置cgroup。所以,可以将 controll groups 理解为 controller (system resource) (for) (process)groups,也就是是说它以一组进程为目标进行系统资源分配和控制。
主要用处:
- Resource limitation: 限制资源使用,比如内存使用上限以及文件系统的缓存限制。
- Prioritization: 优先级控制,比如:CPU利用和磁盘IO吞吐。
- Accounting: 一些审计或一些统计,主要目的是为了计费。
- Control: 挂起进程,恢复执行进程。
在实践中,系统管理员一般会利用CGroup做下面这些事(有点像为某个虚拟机分配资源):
- 隔离一个进程集合(比如:nginx的所有进程),并限制他们所消费的资源,比如绑定CPU的核。
- 为这组进程分配其足够使用的内存
- 为这组进程分配相应的网络带宽和磁盘存储限制
- 限制访问某些设备(通过设置设备的白名单)
②组成结构及规则
组成结构
Cgroups主要由task,cgroup,subsystem及hierarchy构成。
- Task : 在Cgroups中,task就是系统的一个进程。
- Cgroup : Cgroups中的资源控制都以cgroup为单位实现的。cgroup表示按照某种资源控制标准划分而成的任务组,包含一个或多个Subsystems。一个任务可以加入某个cgroup,也可以从某个cgroup迁移到另外一个cgroup。
- Subsystem : Cgroups中的subsystem就是一个资源调度控制器(Resource Controller)。比如CPU子系统可以控制CPU时间分配,内存子系统可以限制cgroup内存使用量。
- Hierarchy : hierarchy由一系列cgroup以一个树状结构排列而成,每个hierarchy通过绑定对应的subsystem进行资源调度。hierarchy中的cgroup节点可以包含零或多个子节点,子节点继承父节点的属性。整个系统可以有多个hierarchy。
1. Subsystems子系统:可控制的资源类型(CPU、MEM等)
想象一下,你家有个大花园,里面种着各种植物,比如蔬菜区、水果区、花卉区等。每个区域都需要不同的照顾,比如
水、阳光、肥料的量
都可能不同。在CGroup中,Subsystems就像是这些不同的区域,代表了操作系统可以控制和限制的资源类型,比如CPU时间、内存使用、磁盘I/O
等。每个子系统负责管理和限制一组特定的资源。
Linxu中为了方便用户使用cgroups,已经把其实现成了文件系统,其目录在/sys/fs/cgroup下:
# 查看可限制的资源
ls -l /sys/fs/cgroup
我们可以看到/sys/fs/cgroug目录下有多个子目录,这些目录都可以认为是收到cgroups管理的subsystem资源。每个subsystem对应如下:
- blkio — 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等等)。
- cpu — 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问。
- cpuacct — 这个子系统自动生成 cgroup 中任务所使用的 CPU 报告。
- cpuset — 这个子系统为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点。
- devices — 这个子系统可允许或者拒绝 cgroup 中的任务访问设备。
- freezer — 这个子系统挂起或者恢复 cgroup 中的任务。
- memory — 这个子系统设定 cgroup 中任务使用的内存限制,并自动生成内存资源使用报告。
- net_cls — 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包。
- net_prio — 这个子系统用来设计网络流量的优先级
- hugetlb — 这个子系统主要针对于HugeTLB系统进行限制,这是一个大页文件系统。
2. Hierarchies层级结构:自己的控制组
现在,假设你想更细致地管理这些区域,可能会
按照功能或者位置把花园划分成几个区域
,每个区域下面再细分。在CGroup里,Hierarchies就是这样的层次结构,它允许你组织和嵌套不同的控制组(Control Groups),形成一个树状结构。每个层级可以挂载不同的子系统,这样就可以在不同的层级上应用不同的资源策略。
3. Control Group控制组:一组进程(类比用户组)
回到花园的例子,如果把每个具体的区域(比如“西红柿区”、“玫瑰区”)看作是一个Control Group,那么它就是一组进程的集合,这些进程共享相同的资源限制和优先级设置。你可以在每个控制组内设定具体某个子系统的使用规则,比如限制西红柿区的水用量,确保玫瑰得到足够的阳光。
4. Tasks运行中的进程:一个进程
Tasks其实就是运行中的进程。在CGroup的上下文中,一个进程(或者线程)可以被分配到某个控制组中,成为那个控制组的成员。这就像是花园里的每株植物,它们各自属于某个区域,并遵循那个区域的管理规则。
四种规则
1. 一个hierarchy附加N个(1个或多个)subsystem
同一个hierarchy能够附加一个或多个subsystem。如 cpu 和 memory subsystems(或者任意多个subsystems)附加到同一个hierarchy。
2. 一个subsystem附加到多个hierarchy
一个 subsystem 可以附加到多个 hierarchy,当且仅当这些 hierarchy 只有这唯一一个 subsystem。即某个hierarchy(hierarchy A)中的subsystem(如CPU)不能附加到已经附加了其他subsystem的hierarchy(如hierarchy B)中。也就是说已经附加在某个 hierarchy 上的 subsystem 不能附加到其他含有别的 subsystem 的 hierarchy 上。
3. 新建一个hierarchy -> root cgroup
系统每次新建一个hierarchy时,该系统上的所有task默认构成了这个新建的hierarchy的初始化cgroup,这个cgroup也称为root cgroup。对于你创建的每个hierarchy,task只能存在于其中一个cgroup中,即一个task不能存在于同一个hierarchy的不同cgroup中,但是一个task可以存在在不同hierarchy中的多个cgroup中。如果操作时把一个task添加到同一个hierarchy中的另一个cgroup中,则会从第一个cgroup中移除。
如:
cpu 和 memory subsystem被附加到 cpu_mem_cg 的hierarchy。而 net_cls subsystem被附加到 net_cls hierarchy。并且httpd进程被同时加到了 cpu_mem_cg hierarchy的 cg1 cgroup中和 net hierarchy的 cg2 cgroup中。并通过两个hierarchy的subsystem分别对httpd进程进行cpu,memory及网络带宽的限制。
4. child task默认与原task在同一个group
进程(task)在 fork 自身时创建的子任务(child task)默认与原 task 在同一个 cgroup 中,但是 child task 允许被移动到不同的 cgroup 中。即 fork 完成后,父子进程间是完全独立的。
Hierarchy层级结构应用场景:云服务器上的多租户应用管理
假设我们是一名云服务提供商,运营着一台高性能的服务器,该服务器上运行着多个租户的应用程序。每个租户都有自己的应用服务组合,可能包含Web服务器、数据库、缓存服务等。为了保证每个租户的资源使用既不会相互干扰,又能充分利用服务器资源,可以使用CGroup的层级结构来实现精细化管理。
- 根层级 (/):这是所有CGroup的起点,你可以在这里挂载所有可用的子系统(CPU、内存、I/O等)。
- 租户层级 (/tenant1, /tenant2, …): 在根层级下,为每个租户创建一个独立的层级,挂载CPU和内存子系统。这样,每个租户的资源使用就被初步隔离了。
- 服务层级 (例如,/tenant1/web, /tenant1/db, /tenant2/web, …): 在每个租户层级下,进一步细分出不同的服务类别,如Web服务、数据库服务等。针对不同服务的特点,可以设置不同的资源限制。例如,数据库服务可能需要较多的内存和I/O带宽,而Web服务则更依赖CPU。
策略:
- 对于/tenant1/db控制组,由于数据库操作通常较重,可以限制其使用不超过总CPU的30%,并分配较大比例的内存和I/O带宽。
- 对于/tenant2/web控制组,由于Web服务器更多涉及轻量级请求处理,可以限制其CPU使用率上限较低,但要求快速响应,因此给予较高的I/O优先级。
③查看系统是否开启cgroups
# 查看os信息(内核版本,硬件架构等)
uname -r# 查看配置文件
cat /boot/config-xxx | grep CGROUP
1 配置文件方式
①支持参数(常用)
仅列出常用配置
②案例:限制进程CPU使用率
## 限制CPU使用
# pgrep xxx # 获取进程PID 14802
ps -ef | grep 进程名mkdir /sys/fs/cgroup/cpu/test# 将PID写入到文件
echo 14802 > /sys/fs/cgroup/cpu/test/cgroup.procs# 该进程限制cpu 20%
echo 20000 > /sys/fs/cgroup/cpu/test/cpu.cfs_quota_us# 解除cpu限制
echo -1 > /sys/fs/cgroup/cpu/test/cpu.cfs_quota_us
- 限制之前:
- 限制进程只能使用0.2核(cpu:20%)
2 系统服务方式systemd
cgroup有两个版本,新版本的cgroup v2即Unified cgroup(参考cgroup v2)和传统的cgroup v1(参考cgroup v1),在新版的Linux(4.x)上,v1和v2同时存在,但同一种资源(CPU、内存、IO等)只能用v1或者v2一种cgroup版本进行控制。systemd同时支持这两个版本,并在设置时为两者之间做相应的转换。对于每个控制器,如果设置了cgroup v2的配置,则忽略所有v1的相关配置。
- systemd通过Unit的配置文件配置资源控制,Unit包括services, slices, scopes, sockets, mount points, 和swap devices六种。systemd底层也是依赖Linux Control Groups (cgroups)来实现资源控制。
V1、V2区别:
- CPU: CPUWeight=和StartupCPUWeight=取代了CPUShares=和StartupCPUShares=。cgroup v2没有"cpuacct"控制器
- Memory:MemoryMax=取代了MemoryLimit=. MemoryLow= and MemoryHigh=只在cgroup v2上支持。
- IO:BlockIO前缀取代了IO前缀。在cgroup v2,Buffered写入也统计在了cgroup写IO里,这是cgroup v1一直存在的问题。
①CGroup V2(常用配置)
文档地址:https://www.kernel.org/doc/Documentation/cgroup-v2.txt
- 这里只列出常用配置,详细请见对应文档
1. CPUQuota:设置服务可用CPU上限
用于设置cgroup v2的cpu.max参数或者cgroup v1的cpu.cfs_quota_us参数。表示可以占用的CPU时间配额百分比。如:20%表示最大可以使用单个CPU核的20%。可以超过100%,比如200%表示可以使用2个CPU核。
2. MemoryLow=bytes:服务最低占用内存
用于设置cgroup v2的memory.low参数,不支持cgroup v1。当unit使用的内存低于该值时将被保护,其内存不会被回收。可以设置不同的后缀:K,M,G或者T表示不同的单位。
3. MemoryHigh=bytes:预期服务占用最高内存(不精准)
用于设置cgroup v2的memory.high参数,不支持cgroup v1。内存使用超过该值时,进程将被降低运行时间,并快速回收其占用的内存。同样可以设置不同的后缀:K,M,G或者T(单位1024)。也可以设置为infinity表示没有限制。
4. MemoryMax=bytes:服务占用最大内存(超过即被kill)
用于设置cgroup v2的memory.max参数,如果进程的内存超过该限制,则会触发out-of-memory将其kill掉。同样可以设置不同的后缀:K,M,G或者T(单位1024),以及设置为infinity。该参数去掉旧版本的MemoryLimit=。
5. TasksMax=N:unit可创建的最大task数
用于设置cgroup的pids.max参数。控制unit可以创建的最大tasks个数。
6. IOReadBandwidthMax=device bytes, IOWriteBandwidthMax=device bytes(带宽上限)
设置磁盘IO读写带宽上限,对应cgroup v2的io.max参数。该参数格式为“path bandwidth”,path为具体设备名或者文件系统路径(最终限制的是文件系统对应的设备名)。数值bandwidth支持以K,M,G,T后缀(单位1000)。可以设置多行以限制对多个设备的IO带宽。该参数取代了旧版本的BlockIOReadBandwidth=和BlockIOWriteBandwidth=。
7. IOReadIOPSMax=device IOPS, IOWriteIOPSMax=device IOPS(磁盘IOPS上限)
设置磁盘IO读写的IOPS上限,对应cgroup v2的io.max参数。格式和上面带宽限制的格式一样一样的。
8. DevicePolicy=auto|closed|strict(设备访问策略)
控制设备访问的策略。
- strict表示:只允许明确指定的访问类型;
- closed表示:此外,还允许访问包含/dev/null,/dev/zero,/dev/full,/dev/random,/dev/urandom等标准伪设备。
- auto表示如果没有明确的DeviceAllow=存在,则允许访问所有设备。auto是默认设置。
9. Delegate=false:开启后unit可以在单其cgroup下创建和管理其自己的cgroup的私人子层级
默认关闭,开启后将更多的资源控制交给进程自己管理。开启后unit可以在单其cgroup下创建和管理其自己的cgroup的私人子层级,systemd将不在维护其cgoup以及将其进程从unit的cgroup里移走。
②CGroup V1(V2被废弃的配置项)
文档地址:https://www.kernel.org/doc/Documentation/cgroup-v2.txt
- 这里只列出CGroupV2被废弃或修改的配置项,详细请见对应文档
- 这些是旧版本的选项,新版本已经弃用。列出来是因为centos 7里的systemd是旧版本,所以要使用这些配置。
1. CPUShares=weight, StartupCPUShares=weight(获取CPU的权重值)
进程获取CPU运行时间的权重值,对应cgroup的"cpu.shares"参数,取值范围2-262144,默认值1024。
2. MemoryLimit=bytes:进程内存使用上限
对应cgroup的"memory.limit_in_bytes"参数。支持K,M,G,T(单位1024)以及infinity。默认值-1表示不限制。
3. BlockIOWeight=weight, StartupBlockIOWeight=weight:磁盘IO的权重
对应cgroup的"blkio.weight"参数。取值范围10-1000,默认值500。
4. BlockIODeviceWeight=device weight:指定磁盘的IO权重
对应cgroup的"blkio.weight_device"参数。取值范围1-1000,默认值500。
5. BlockIOReadBandwidth=device bytes, BlockIOWriteBandwidth=device bytes:磁盘IO带宽的上限配置
对应cgroup的"blkio.throttle.read_bps_device"和 "blkio.throttle.write_bps_device"参数。支持K,M,G,T后缀(单位1000)。
③案例:限制服务CPU使用率
# 修改服务配置文件
vim /etc/systemd/system/test.service[Unit]
Description=test service
After=network.target[Service]
ExecStart=xxxxxx
ExecStopPost=xxxxxx
Restart=always
CPUQuota=75% # 配置服务CPU最多只能占用0.75核[Install]
WantedBy=multi-user.target
# 重新加载服务
systemctl daemon-reload# 重启服务
systemctl restart test.service
参考文章:
https://www.cnblogs.com/jimbo17/p/9107052.html
https://blog.csdn.net/lisemi/article/details/94021498
相关文章:

Linux CGroup资源限制(概念限制进程CPU使用)
Linux CGroup资源限制(详解) 最近客户认为我们程序占用cpu过高,希望我们限制,排查之后发现是因为程序频繁gc导致,为了精细化、灵活的的限制,想到了使用Linux CGroup。 0 前置知识 ①概念及作用 官网&#…...

Latex中标注通讯作者
** 直接使用脚注,不用添加宏包 多个同地址的并列,建议加点空格,好看一些 ** \title{xxxxxxxxxxxxxxxxxxx}\author{xxxxxxxxxxxxxxxxxxx\footnote{Corresponding author} ,bbbbbbbbbbbbbbbbbbb}\address{xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx…...

PyQt5开发笔记:1.环境搭建与界面美化
推荐视频教程: https://www.bilibili.com/video/BV1LT4y1e72X?p23&vd_source7ab611f3afb3d469faad93d3996f99ba 一、打开网址,点击下载 https://build-system.fman.io/qt-designer-download 下载后,点开exe 不推荐:http…...

公派/自费访问学者申请出国访学的常见问题解答(下)
06、学术背景和研究成果要求? 访学是面向学术单位和企事业单位开放的。 针对学术单位,比如高校与科研院所,学科内涉及的论文发表,课题研究,专利,著作,含金量较高的奖项等背景都是国外比较看重…...
完全指南:C语言学习资源汇总
C语言是编程学习的基石,无论是为了职业发展还是个人兴趣,掌握C语言都是技术生涯的重要一步。为了帮助初学者和有经验的程序员更好地学习和深化对C语言的理解,我们汇总了一系列优秀的书籍和在线资源。这些资源将帮助你从基础知识到高级概念&am…...

Kubernetes——Ingress详解
目录 前言——Service策略的作用 1.外部访问方案 2.使用场景和限制 2.1NodePort 2.2LoadBalancer 2.3externalIPs 2.4Ingress 3.Ingress如何实现对外服务 4.LB和Ingress结合起来实现对外服务的过程 一、Ingress 1.定义 2.组成 3.工作原理 4.总结 二、部署Nginx-I…...

反射、类加载、静态代理,jdk动态代理,cglib代理
一、 反射 反射是在程序运行状态下,动态获取类的结构(属性,构造器,方法,注解),动态的创建类对象然后调用类中的属性方法。反射的起源Class,Class中包含类反射要使用的API 获取Class的…...

MySQL Hints:控制查询优化器的选择
码到三十五 : 个人主页 MySQL Hints是优化数据库查询性能的一种强大工具。它们允许开发者在SQL查询中嵌入指令,以影响MySQL优化器的决策过程。在某些情况下,优化器可能无法选择最佳的查询执行计划,这时我们可以使用Hints来引导优化…...

【TB作品】msp430g2553单片机,OLED,PCF8591,ADC,DAC
硬件 OLED PCF8591 /** OLED* VCC GND* SCL接P2^0* SDA接P2^1*//** PCF8591* VCC GND* SCL接P1^4* SDA接P1^5*//* 板子上按键 P1.3 *//* 单片机ADC输入引脚 P1.1 *//* 说明:将PCF8591的DAC输出接到单片机ADC输入引脚 P1.1,单片机采集电压并显示 */功能…...

C#WPF数字大屏项目实战10--不良指标分页
1、区域划分 2、区域布局 3、视图模型 4、控件绑定 5、运行效果 走过路过,不要错过,欢迎点赞,收藏,转载,复制,抄袭,留言,动动你的金手指,财务自由...

数字塔问题
#include<iostream> using namespace std; //从下向上得到最优值 void dtower(int a[][100],int s[][100],int n) {for(int in; i>1; i--){for(int j1; j<i; j){if(in)s[i][j]a[i][j];else{int ts[i1][j];if(t<s[i1][j1])ts[i1][j1];s[i][j]a[i][j]t;}}} } void…...

【介绍下Pwn,什么是Pwn?】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...

Python:b站多个视频爬取下载
📚博客主页:knighthood2001 ✨公众号:认知up吧 (目前正在带领大家一起提升认知,感兴趣可以来围观一下) 🎃知识星球:【认知up吧|成长|副业】介绍 ❤️如遇文章付费,可先看…...

Java常规题技术分享
一、数组排序和添加成员 设计类Student和类StudentClass。 (1) 类Student有字符串属性name、double属性grade和int属性age 有带参数的构造方法,可设置三个属性的值 有各个属性的置取方法 (2)类StudentClass有Student数组属性stus存放班级成员,有int…...
Pytorch语义分割(1)-----加载数据
在语义分割中用到的数据无非就是原始图片(image)和标注后得到的mask图片,所以在读取数据的时候只要返回图片和标签信息就OK 了。 import torch import os import numpy as np from torch.utils.data import Dataset from utils_func import …...
Java中加号的多种用途
在Java中, 符号有多种用途,主要根据上下文而定。以下是在Java中的一些主要用途: 加法运算符: 这是最常见的用途,用于数字相加。 int a 5;int b 3;int sum a b; // sum is 8 字符串连接符: 当用…...
React useCallback用法
useCallback 是 React 中的一个 Hook,它用于优化性能,通过缓存函数的引用来避免在组件的每次渲染时都创建新的函数实例。这对于避免不必要的子组件重新渲染特别有用,因为如果传递给子组件的回调函数在每次渲染时都不同,即使子组件…...
Flutter 中的 ErrorWidget 小部件:全面指南
Flutter 中的 ErrorWidget 小部件:全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架,它允许开发者使用 Dart 语言构建高性能、美观的应用。在 Flutter 的丰富组件库中,ErrorWidget 是一个特殊的组件,用于在渲染过程中捕获…...
【数据结构】穿梭在二叉树的时间隧道:顺序存储的实现
专栏引入 哈喽大家好,我是野生的编程萌新,首先感谢大家的观看。数据结构的学习者大多有这样的想法:数据结构很重要,一定要学好,但数据结构比较抽象,有些算法理解起来很困难,学的很累。我想让大家…...

【数据结构与算法 经典例题】链表的回文结构(图文详解)
💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《数据结构与算法 经典例题》C语言 期待您的关注 目录 一、问题描述 二、解题思路 三、C语言代码实现 一、问题描述 二、解…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...

基于Springboot+Vue的办公管理系统
角色: 管理员、员工 技术: 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能: 该办公管理系统是一个综合性的企业内部管理平台,旨在提升企业运营效率和员工管理水…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...

MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...