mysql面试(四)

news2024/11/13 21:38:22

前言

本章节有些长,主要的篇幅是介绍缓存页的算法,如何快速的定位哪些是没有用过的,哪些是用过的,哪些是要淘汰掉的。
建议可以阅读一下这里面LRU算法相关的内容,和很多组件里面基本原理都是想通的,比如redis的淘汰算法等。

缓存页Buffer Pool

为什么需要缓存

在上面的时候,我们讲过,mysql中的真实数据确实都是存储在磁盘文件上的,这就是在物理层面的存储,哪怕服务器宕机了,也不会影响这些磁盘上被写入的数据。
但是这里存在一个问题,就是在我们读写的时候,如果直接读写磁盘上的数据,速度会特别慢,通常以每秒几十至几百兆字节。因为这是磁盘在物理层面读取的限制,比如机械硬盘读取的时候,是移动机械臂,并且将磁盘转动到指定的扇区才能读取或者写入数据。固态硬盘虽然是通过电子芯片方式来存储数据,读写速度比机械硬盘快的多,但是获取数据也是要通过固定的电子路径来处理。所以磁盘中的数据注定了不能做到快速读写。
但是我们在线上的时候获取数据都是纳秒级的,这时候就需要用到缓存了,也就是数据直接从内存中读取。要注意的是,这个缓存并不是我们自己升级电脑时候搞的那个内存条。而是在处理器(CPU)中集成的缓存区。这些展开讲就没个头了,这里只是简单提一下。

什么是缓存页

刚才说了,当我们读写磁盘数据的时候,其实都是在缓存中修改的。那么在缓存中肯定是要给mysql提前划分出来一片区域来存储这些缓存数据,而这个区域就叫做缓存池Buffer Pool。
这个缓存池中存储数据的时候,为了我们读写的时候方便,也会在其中划分出来一片片的小内存区域。而这个小小的内存分区就是缓存页。
这个缓存页是默认的大小 16KB,而缓存池的默认大小是128M。如果服务器的内存足够大,完全可以给Buffer Pool分配的大一些。比如服务为16核32G的机器,就可以分配2G的配置是完全没问题的。
缓存页16K这个大小也是有讲究的,他是和mysql磁盘存储数据也大小完全一致的。
我们都知道,mysql数据库核心的存储模型就是表+字段+行的概念,也就是说,我们知道数据库中的有一个个的表,每个表有一行行个的数据。每行数据都有自己的字段值。
但是mysql对这些数据抽象出来了一个数据页的概念,把很多行的数据放在了一个数据页中。那么我们查询的时候,就是先确定要查询的数据存储在哪个数据页中,然后再到对应的数据页获取数据。这个流程会涉及到索引,我们后面再详细说。
需要注意的一点是,每个缓存页都有一些描述数据,大概占缓存页的5%左右,也就是800个字节吧,所以当我们设置Buffer Pool 128M的时候,实际上的大小会超出一些。
如图:
在这里插入图片描述

如何初始化Buffer Pool

只要在数据库启动的时候,就会按照我们设置的Buffer Pool大小来向操作系统进行申请,划分出来一块相应的区域。
当这块内容申请完毕之后,数据库就会按照默认的缓存页每个16K的大小以及对应的800个字节描述数据的大小在Buffer Pool中划分出来一个个的缓存页和一个对应的描述数据。
当划分完成之后,就是我们上面的那张图的样式了。当然,这时候所有的缓存页中的数据都是空的,等到有请求要对数据进行增删改查的时候,才会把对应的数据从磁盘文件的数据页中提出来放入缓存页中。

如何判断哪些缓存页是空的

当我们想要将数据从磁盘的数据页中拿出来,放入缓存页的时候,不单单是简单的放入缓存页。还要先确定缓存页是否为空。 就好像把大象放进冰箱的时候,也要先确定里面是不是有个长颈鹿,对吧。
那如果按照一个简单的方式,想要存入这个缓存页,先看一眼有没有数据,没有的话放入,有的话去看下一个。这样的话缓存页少的话当然没有问题,但是存储数据肯定不会是简单一点点的数据而已,就按照最简单的128M,16k一个缓存,换算下来,也得好几千个。那能判断几千次吗? 肯定不能这样搞。
所以这里就有一个free链表的概念,是一个双向链表的结构。每一个节点都是缓存的描述数据储存地址。并且这个链表中的描述数据都是指向空闲的数据页。
我们可以想象一下,当初始化的时候,所有的数据页都是空的,那么所有的描述数据都会存放在这个free链表中。如图所示:
在这里插入图片描述

free链表

大家可以看到,上面有一个由多个节点组成的链表数据,只要数据页是空闲的,那么他对应的描述数据都会加入这个链表中,每个节点都会同时指向自己的前后两个节点。
还有一点就是free链表有一个基础节点,他会引用链表的头节点和尾节点,并且里面还存储了当前有链表中包含多少描述数据节点,也就是有多少个缓存页。
那么free链表是怎么存储的呢,难道也要开辟出来一个单独的数据块来存储吗,那这样一搞,不就会导致描述数据冗余存储了? 或者是再多出来一个用来描述 描述数据 的数据结构吗? 玩套娃来了这是
当然不会这样搞,其实这个free链表是一个抽象的概念,他的本身就是这些描述数据。每一个描述数据都会有两个指针,一个是free_pre,一个是free_next,用来指向上一个free链表节点,和下一个free链表节点。
这样一来就像两条绳子一样,把所有的空闲描述数据给串联起来,构成一个free链表。
对于这个链表而言,只有一个基础节点不是描述数据。存放的就是链表头尾节点的地址,还有free链表中有多少个节点。
为什么要使用双向链表,按照当前逻辑,单向链表也是可以实现的。
因为只有双向链表才可以获取到上一个节点,否则我们直接申请最后面节点的话,是无法直接修改上一个节点的指针的。

将数据读取到缓存页中

既然现在已经知道哪些缓存页是空的了,那么就可以直接从磁盘中拿数据,然后从free链表中拿一个节点的描述数据,获取到对应缓存页的地址。
再把这些数据写入到缓存页中去了,同时将数据的表空间之类的信息写入到描述数据中。
最后要做的就是将这个已经使用的描述数据从free链表中移除掉
比如这里有三个节点,每个节点都指向了前后节点,要移除尾部节点的时候,只需要将第二个节点的naxt指向改为null,链表中就不存在第三个节点了。
在这里插入图片描述

如何知道数据是否已经被缓存

现在,已经可以判断哪些缓存页为空,可以将数据存进去了。但是还有一个问题要解决,就是缓存这个数据的时候,怎么知道这个数据已经被缓存过了呢? 肯定也不能是一个个描述数据去看的。
所以这时候还有另一个数据结构,一个哈希表数结构
每当我们在缓存页中存入数据,就会通过“表空间号+数据页号”作为一个key,将缓存页的地址作为value,将其存入哈希表中。
存疑
那么,当想要缓存数据的时候,先通过“表空间号+数据页号”作为一个key去哈希表中查询一下看数据是否存在,如果存在的话肯定就是已经被缓存了,不需要重复缓存。

在这里插入图片描述

脏页和flush链表

根据上面我们说过的一个更新链路来看,肯定是要先更新缓存,然后InnoDB会去定时把数据刷到磁盘上。而这些先在缓存页中修改的,并未刷到磁盘中的数据,就是属于脏页。
最终这些脏页肯定都是要刷到磁盘中的,但是肯定不会所有的缓存页都需要刷回去啊。这时候就需要有个机制来记录哪些数据页是需要回刷的。
于是flush链表就产生了,他的本质和free链表类似,也是由被修改过的数据页描述块指向前后两个节点,形成一个双线链表。
凡是被修改过的数据页,都会被加入这个flush链表中。如图:在这里插入图片描述

LRU淘汰算法

现在已经解决了空页问题,重复缓存问题,数据回刷问题。
但是还有一个问题,因为Buffer Pool的空间肯定是比磁盘中的空间小的,肯定会有占满的时候,所以Buffer Pool中缓存的数据一定是部分数据。当访问到Buffer Pool中不存在的数据,要去磁盘中找,找到之后也是要放在缓存中的。这个时候,free链表中已经没有空余数据页了,该怎么去删除缓存中现有的数据页呢?
如果随便删的话,删到热点数据怎么办。就是那种本来频繁查询使用的数据,如果从缓存中移除的话肯定还是会很快再次被更新到缓存中。那这多次去磁盘中查询,不又浪费了资源么。我们肯定是要提高缓存命中率的。
所以需要有一个淘汰机制来确定哪些数据页是被使用次数最少的。淘汰掉这些不频繁使用的数据页才是最好的方法。
此时引入了一个新的LRU链表,所谓的LRU就是Least Recetly Used,最近最少使用的意思。
通过这个LRU链表,我们可以确定有哪些缓存页是最近最少被会用的。那么当缓存页需要腾出来一个,用来放入新数据的时候,不就可以直接拿着用了么。PS:插一句,Redis淘汰机制也有用这个类似算法。
先简单了解一下这个LRU链表的工作原理。
大致意思是,每当从磁盘中加载一个数据页的时候,就把这个缓存页的描述数据放到LRU链表的头部来。这样一来所有的缓存页数据都会在LRU链表中,而且,当链表中某一个缓存页被访问了,也会把这个对应的描述数据移动到LRU链表的头部。
这样一来,每当Buffer Pool中的缓存页被占满的时候,就可以从LRU链表的尾部来直接拿一个缓存页,他就是被访问最少的一个。
在这里插入图片描述

预读机制导致的LRU链表隐患

什么是预读机制? 哪些情况下会触发呢?为什么需要预读机制?
简单一点来说,就是当访问数据库其中一些数据页的时候,并且刚好触发了预读的规则,那么mysql会把相邻的数据页都加载到缓存中去。但是这些数据页不一定是你真正要访问的数据,就会导致把LRU链表中的热点数据给挤到链表的队末,导致热点数据被淘汰掉。
有两种情况会被触发的规则,一种是有个变量innodb_read_ahead_threshold,这个变量的值,默认是56。如果按照顺序访问了一个区中多个数据页,达到了这个数量级的话,就会触发预读机制。把下一个相邻区中的所有数据都给加载到缓存中去。
还有一种是Buffer Pool中如果缓存了一个区中的连续13个数据页,而且这些数据页都是被频繁访问的,也会直接触发预读机制,把这个区中的所有数据页都加载到缓存中。这个是由innodb_random_read_ahead来控制的,默认是OFF,关闭状态。
全表扫描

基于冷热数据分离的思想设计LRU链表

上面说了,当有些不一定使用的缓存页混入了LRU链表中出现了问题。
所以真正的LRU链表,会被拆分为两部分,一部分是热数据,一部分是冷数据。冷数据占比默认情况是37%,可以通过innodb_old_blocks_pct参数控制的,他默认是37 。
如图:
在这里插入图片描述
当数据第一次加载的时候,会把缓存页放在冷数据区域的头部。
既然刚开始的时候,是默认放在冷数据区域中,那么肯定有规则是要挪到热数据区域的。
这个规则就是,当一个缓存页被加载到冷数据区域头部,如果1s之后还会再次访问的话。就会把这个缓存页挪动到热数据区域的头部。
那为什么不是再次访问之后就立刻就挪到头部呢? 是这样,既然我们加载了这个缓存页,那么肯定是可能在短时间被访问的,所以查询了一次之后并不能说明是被频繁访问的。如果1s之后还能被访问,就证明这些数据是热点数据。
这样一来的话就可以解决上面的热点数被挤到LRU链表尾部的问题了。哪些被预读机制和全盘扫描机制加载到LRU链表冷数据区域的缓存页,1s之后没有进行访问的话,就会一直都呆在冷数据区域。
当缓存页不够用的时候,就可以直接从冷数据区域的尾部来淘汰一部分缓存页,刷入磁盘就可以了。
还有一点,冷热数区域是没有固定的节点位置,当冷数据区的缓存页被放到热数据区之后。热数据区的数据肯定就会被往后挤咯。那么自然就被挤到冷数据区了。因为冷热数据区是按照百分比来划分的。

LRU链表热数据区域的优化

我们现在应该都知道,热数据区域的缓存页都是比较容易被访问的。那么既然都是容易被访问的,那本来就处于热数据区域头部附近的,那些缓存页,被访问的时候,还需要再次移动到头部吗?
确实不用,只有热数据区域的后4/1被访问的时候,才会直接将其移动到热数据区域的头部,这样可以减少节点的移动,进而减少内存消耗。

刷新脏页到磁盘

上面说过,当数据页变成脏页后,是存在flush链表中的。
而后台有一个专门的线程,每隔一段时间就负责吧脏页刷新到磁盘中去,这样可以不影响用户的请求。 主要有两种方式。
一种是从LRU链表的冷数据区尾部刷新一部分缓存页到磁盘。
另一种是从flush链表中刷新一部分页面到磁盘中。刷新的速率取决于当时的系统忙不忙。
但是有的时候刷新比较慢,导致用户在查询数据更新缓存页的时候没有可以用的空缓存页使用。这时候就要尝试在 LRU链表的冷数据区尾部看看有没有可以直接释放掉的未修改页面。如果没有的话就不得不将 LRU链表尾部的脏数据页先刷新到磁盘才行。但是与磁盘的交互是很费时间的。
极端情况下有可能出现,用户的请求导致批量的从flush链表刷新数据到磁盘的情况。这就需要另一种机制来处理了。我们后面再讲。

多个Buffer Pool实例

Buffer Pool的本质是InnoDB向操作系统申请的一块连续的内存空间,当多线程访问的时候。就需要对各种链表加锁处理啥的,那这样一来如果Buffer Pool特别大,访问请求特别多的情况下,肯定会影响处理速度。
所以当Buffer Pool特别大的时候,我们可以把它们拆分为多个Buffer Pool,每个Buffer Pool又都是不相关的实例,它们都是独立的,独立的申请内存空间,独自维护,独自管理各种链表什么的。这样一来多线程访问不同的缓存池就不会受影响,从而提高并发访问的处理能力。通过这个参数设置。
[server]
innodb_buffer_pool_instances = 2
需要注意的是,并不是Buffer Pool实例越多越好,分别对缓存池进行管理也是一笔不小的开销。所以innodb默认:当innodb_buffer_pool_size的值小于1G的时候设置多个实例是无效的,InnoDB会默认把innodb_buffer_pool_instances 的值修改为1
也就是说,当缓存池设置的大于等于1G的时候,才可以分为多个实例。

Buffer Pool实例的chunk机制

msyql在5.7.5版本之后,支持了Buffer Pool在服务器运行过程中进行动态调整。
实现这个首先我们要先记得Buffer Pool的本质是InnoDB向操作系统申请的一块连续的内存空间。那么想要实现动态调整的话,就把这个Buffer Pool的下级再次拆分,拆分一个chunk的概念。一个Buffer Pool其实是由多个chunk组成的,一个chunk就代表一片连续的空间。 这些chunk的缓存页,还是通过一套链表来进行维护。
如图:
在这里插入图片描述

查看buffer pool的状态

通过SHOW ENGINE INNODB STATUS 语句
mysql> SHOW ENGINE INNODB STATUS\G

(...省略前边的许多状态)
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 13218349056;
Dictionary memory allocated 4014231
Buffer pool size 786432
Free buffers 8174
Database pages 710576
Old database pages 262143
Modified db pages 124941
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 6195930012, not young 78247510485
108.18 youngs/s, 226.15 non-youngs/s
Pages read 2748866728, created 29217873, written 4845680877
160.77 reads/s, 3.80 creates/s, 190.16 writes/s
Buffer pool hit rate 956 / 1000, young-making rate 30 / 1000 not 605 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 710576, unzip_LRU len: 118
I/O sum[134264]:cur[144], unzip sum[16]:cur[0]
--------------
(...省略后边的许多状态)

我们来详细看一下这里边的每个值都代表什么意思:

Total memory allocated :代表 Buffer Pool 向操作系统申请的连续内存空间大小,包括全部控制块、缓
存页、以及碎片的大小。
Dictionary memory allocated :为数据字典信息分配的内存空间大小,注意这个内存空间和 Buffer Pool
没啥关系,不包括在 Total memory allocated 中。
Buffer pool size :代表该 Buffer Pool 可以容纳多少缓存 页 ,注意,单位是 页 !
Free buffers :代表当前 Buffer Pool 还有多少空闲缓存页,也就是 free链表 中还有多少个节点。
Database pages :代表 LRU 链表中的页的数量,包含 young 和 old 两个区域的节点数量。
Old database pages :代表 LRU 链表 old 区域的节点数量。
Modified db pages :代表脏页数量,也就是 flush链表 中节点的数量。
Pending reads :正在等待从磁盘上加载到 Buffer Pool 中的页面数量。
当准备从磁盘中加载某个页面时,会先为这个页面在 Buffer Pool 中分配一个缓存页以及它对应的控制块,
然后把这个控制块添加到 LRU 的 old 区域的头部,但是这个时候真正的磁盘页并没有被加载进来, Pending
reads 的值会跟着加1。
Pending writes LRU :即将从 LRU 链表中刷新到磁盘中的页面数量。
Pending writes flush list :即将从 flush 链表中刷新到磁盘中的页面数量。
Pending writes single page :即将以单个页面的形式刷新到磁盘中的页面数量。
Pages made young :代表 LRU 链表中曾经从 old 区域移动到 young 区域头部的节点数量。
这里需要注意,一个节点每次只有从 old 区域移动到 young 区域头部时才会将 Pages made young 的值加
1,也就是说如果该节点本来就在 young 区域,由于它符合在 young 区域1/4后边的要求,下一次访问这个页
面时也会将它移动到 young 区域头部,但这个过程并不会导致 Pages made young 的值加1。
Page made not young :在将 innodb_old_blocks_time 设置的值大于0时,首次访问或者后续访问某个处
在 old 区域的节点时由于不符合时间间隔的限制而不能将其移动到 young 区域头部时, Page made not
young 的值会加1。
这里需要注意,对于处在 young 区域的节点,如果由于它在 young 区域的1/4处而导致它没有被移动到
young 区域头部,这样的访问并不会将 Page made not young 的值加1。
youngs/s :代表每秒从 old 区域被移动到 young 区域头部的节点数量。
non-youngs/s :代表每秒由于不满足时间限制而不能从 old 区域移动到 young 区域头部的节点数量。
Pages read 、 created 、 written :代表读取,创建,写入了多少页。后边跟着读取、创建、写入的速
率。
Buffer pool hit rate :表示在过去某段时间,平均访问1000次页面,有多少次该页面已经被缓存到
Buffer Pool 了。
young-making rate :表示在过去某段时间,平均访问1000次页面,有多少次访问使页面移动到 young 区
域的头部了。
需要大家注意的一点是,这里统计的将页面移动到 young 区域的头部次数不仅仅包含从 old 区域移动到
young 区域头部的次数,还包括从 young 区域移动到 young 区域头部的次数(访问某个 young 区域的节
点,只要该节点在 young 区域的1/4处往后,就会把它移动到 young 区域的头部)。
not (young-making rate) :表示在过去某段时间,平均访问1000次页面,有多少次访问没有使页面移动
到 young 区域的头部。
需要大家注意的一点是,这里统计的没有将页面移动到 young 区域的头部次数不仅仅包含因为设置了
innodb_old_blocks_time 系统变量而导致访问了 old 区域中的节点但没把它们移动到 young 区域的次数,
还包含因为该节点在 young 区域的前1/4处而没有被移动到 young 区域头部的次数。
LRU len :代表 LRU链表 中节点的数量。
unzip_LRU :代表 unzip_LRU链表 中节点的数量(由于我们没有具体唠叨过这个链表,现在可以忽略它的
值)。
I/O sum :最近50s读取磁盘页的总数。
I/O cur :现在正在读取的磁盘页数量。
I/O unzip sum :最近50s解压的页面数量。
I/O unzip cur :正在解压的页面数量。
这些大概看一下就行了,真到用的时候可以再查。

预告

篇幅问题, 下一章节开始介绍,缓存页和索引的关系,缓存页是如何形成索引的,索引的具体构成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1947161.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mac m1安装 MongoDB 7.0.12

一、下载MongoDB MongoDB 社区版官网下载 二、安装配置MongoDB 1.解压下载的压缩包文件,文件夹重命名为mongodb; 2.将重命名为mongodb的文件夹,放在/usr/local 目录下 3.在/usr/local/mongodb 目录下,新建data 和 log这两个文件夹&#…

【word转pdf】【最新版本jar】Java使用aspose-words实现word文档转pdf

【aspose-words-22.12-jdk17.jar】word文档转pdf 前置工作1、下载依赖2、安装依赖到本地仓库 项目1、配置pom.xml2、配置许可码文件(不配置会有水印)3、工具类4、效果 踩坑1、pdf乱码2、word中带有图片转换 前置工作 1、下载依赖 通过百度网盘分享的文…

css实现线条中间高亮,左右两边模糊(linear-gradient的运用)

效果&#xff1a; <div class"line"></div> .line {height: 1px;background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, #a9c2ff 50%, rgba(255, 255, 255, 0) 100%);border-radius: 4px 4px 4px 4px; } CSS实现边框底部渐变色的方法:(最简单…

Python基础-语句结构、数据输入

1、分行与缩进 分行&#xff1a; python每一句语句有长度限制&#xff0c;因此不应过长&#xff0c;如果语句过长可以使用\续航符或者加上()控制换行。 []&#xff0c;{}, ()可以直接跨越多行&#xff0c;在列表、字典、元组中需要换行的时候可以不用添加续行符号。 缩进&…

【Java题解】以二进制加法的方式来计算两个内容为二进制数字的字符串相加的结果

&#x1f389;欢迎大家收看&#xff0c;请多多支持&#x1f339; &#x1f970;关注小哇&#xff0c;和我一起成长&#x1f680;个人主页&#x1f680; &#x1f451;目录 分析&#xff1a;&#x1f680; 数字层面分析⭐ 字符串层面分析⭐ 代码及运行结果分析:&#x1f6…

如何在 Windows 11 中录制屏幕

录制屏幕是Windows 11上一项非常有用的功能。在专业方面&#xff0c;它允许您捕获屏幕以突出显示问题或向同事展示新的工作流程。您还可以录制演示文稿&#xff0c;并在整个公司内共享。对于游戏&#xff0c;它可以让您录制动作片段&#xff0c;然后可以与朋友分享或在线发布。…

Vue---vue3+vite项目内使用devtools,快速开发!

背景 我们在前期开发时&#xff0c;一般使用chrome或者edge浏览器&#xff0c;会使用vue-devtools或react-devtools&#xff08;此插件个人未使用&#xff0c;可百度下是否可内嵌入项目&#xff01;&#xff09;来审查vue项目&#xff1b;这个需要安转浏览器插件才可支持&…

Python脚本通过Kvaser和ECU进行CAN通信

1 安装软件 Kvaser官网: https://kvaser.com/download/ 下载下面三个软件包: 下载完如下图: 双击安装这三个软件。 2 查看设备信息 将 Kvaser 工具连接电脑和 ECU,工具包含两个物理通道, CAN I 和 CAN II,我的是用 CAN I 和 ECU 连接的。 然后打开下面的软件, …

2024-06学习笔记

1.事务与数据库链接的占用 如果用Transactional注解&#xff0c;那在第一次与数据库交互的时候&#xff0c;就会打开数据库链接&#xff0c;再整个方法执行完&#xff0c;才会关闭数据库链接。 即使后边用的事务传播是required_new,那之前的事务也是被挂起&#xff0c;不会被…

前端面试宝典【Javascript篇】【3】

欢迎来到《前端面试宝典》&#xff0c;这里是你通往互联网大厂的专属通道&#xff0c;专为渴望在前端领域大放异彩的你量身定制。通过本专栏的学习&#xff0c;无论是一线大厂还是初创企业的面试&#xff0c;都能自信满满地展现你的实力。 核心特色&#xff1a; 独家实战案例…

大语言模型-GPT2-Generative Pre-Training2

一、背景信息&#xff1a; GPT2是2019年由OpenAI 提出的预训练语言模型。 GPT2提出语言模型式无监督的多任务学习 。旨在通过无监督学习也能达到和finetune一样的效果&#xff0c;并且拥有更强的泛化能能力。 即提出利用语言模型做下游任务时&#xff0c;不需要下游任务的任何…

Ubuntu 22.04如何设置中文输入法

前言 近期整理了一下之前在ubuntu 22.04 中如何设置中文输入法的过程&#xff0c;对于本人比较适应读中文写中文来说&#xff0c;这是我安装后的第一步。 一、流程 1.1 安装中文语言包&#xff08;如果还未安装&#xff09; 首先是安装中文语言包&#xff0c;直接在终端输入…

Elasticsearch集群配置-节点职责划分 Hot Warm 架构实践

前言 本文主要讲了ES在节点部署时可以考虑的节点职责划分&#xff0c;如果不考虑节点部署&#xff0c;那么所有节点都会身兼数职&#xff08;master-eligible &#xff0c;data&#xff0c;coordinate等&#xff09;&#xff0c;这对后期的维护拓展并不利&#xff0c;所以本文…

SSRF中伪协议学习

SSRF常用的伪协议 file:// 从文件系统中获取文件内容,如file:///etc/passwd dict:// 字典服务协议,访问字典资源,如 dict:///ip:6739/info: ftp:// 可用于网络端口扫描 sftp:// SSH文件传输协议或安全文件传输协议 ldap://轻量级目录访问协议 tftp:// 简单文件传输协议 gopher…

算法——滑动窗口(day8)

30.串联所有单词的子串 30. 串联所有单词的子串 - 力扣&#xff08;LeetCode&#xff09; 必看&#xff01;&#xff01;&#xff01;本题是我们上次写的438.异位词的进阶版&#xff0c;可参考本篇文章&#xff1a;算法——滑动窗口&#xff08;day7&#xff09;-CSDN博客来…

c++笔记2

目录 2.2 栈底&#xff08;bottom&#xff09; } 大数乘大数 节点&#xff1a;包含一个数据元素及若干指向子树分支的信息 。 节点的度&#xff1a;一个节点拥有子树的数目称为节点的度 。 叶子节点&#xff1a;也称为终端节点&#xff0c;没有子树的节点或者度为零的节点…

vue3+openLayers触摸事件显示弹窗

<template><!--地图--><div class"distributeMap" id"distributeMap"></div><!--弹窗--><section ref"popup" id"popupDiv" class"popup">{{ state.popupParams.name }}</section&g…

OpenGauss和GaussDB有何不同

OpenGauss和GaussDB是两个不同的数据库产品&#xff0c;它们都具有高性能、高可靠性和高可扩展性等优点&#xff0c;但是它们之间也有一些区别和相似之处。了解它们之间的关系、区别、建议、适用场景和如何学习&#xff0c;对于提高技能和保持行业敏感性非常重要。本文将深入探…

电脑ip地址怎么改?修改技巧大放送!

在现代网络环境中&#xff0c;IP地址的设置对于连接互联网和局域网至关重要。无论是因为网络配置的需求&#xff0c;还是出于隐私和安全考虑&#xff0c;学会更改电脑的IP地址是一项有用的技能。本文将介绍电脑ip地址怎么改的3种方法&#xff0c;帮助您根据不同需求灵活调整网络…

Go并发GMP调度模型

如何知道一个对象是分配在栈上还是堆上&#xff1f; Go和C不同&#xff0c;Go的逃逸分析是在编译器完成的&#xff1b;go局部变量会进行逃逸分析。如果变量离开作用域后没有被引用&#xff0c;则优先分配到栈上&#xff0c;否则分配到堆上。那么如何判断是否发生了逃逸呢&#…